진행 중 · 2026년 5월 25일
daeseon.ai
이 사이트. 이중언어 블로그 + 드래프트/배포용 비공개 어드민 대시보드.
- 역할
- Solo
- 스택
- Next.js 15 · TypeScript · Tailwind · MDX · Vercel
지금 보고 있는 이 블로그. 제약(글 톤, 어드민 기능, 배포)을 템플릿이 아니라 내가 정하려고 처음부터 직접 만들었다.
무엇을 하는가
- 이중언어 글 (EN 기본, KO는
/ko),translationKey로 교차 링크. - MDX + Format A(4톤 다중 등록) + Format B(프로젝트 회고) 글쓰기 규약이 에디터에 박혀있음.
- 비공개 어드민(
/admin) — 비밀번호 게이트, JWT 세션 쿠키, GitHub에 commit하는 글 에디터. - 언어별 RSS, hreflang 사이트맵, 어드민 경로는 robots 차단.
왜
몇 년 동안 개인 문서에만 글을 쓰고 공개하지 않았다. 이 사이트가 그 루프를 끊기 위한 장치다.
아직 안 되는 것
- 실 글별 분석 (트래픽 의미 있을 때까지 보류).
- 크로스포스팅 연결 — webhook slot은 있고, 실제 도구는 별개
crosspost-bot프로젝트.
프로젝트 로그
이 프로젝트를 만들면서 남긴 트러블슈팅 · 회고 · 업데이트의 시간순 기록.
MDX broke on `$\mathbb{R}^d$` with `R is not defined`
트러블슈팅2026년 5월 25일 · 1 분
Curly braces in math notation are JSX expressions to MDX. The build crashed on a sample embeddings post.
Stack and storage: Next.js 15 + GitHub commit-as-database
기술 회고2026년 5월 25일 · 1 분
Why I picked Next.js 15 + Vercel + GitHub Contents API for storage instead of a database.
Why I split content into post / note / knowledge / log
기술 회고2026년 5월 26일 · 2 분
One bucket for everything fails three different audiences. Four content types with different visibility defaults each.
EROFS on every Vercel publish — production fs is read-only
트러블슈팅2026년 5월 26일 · 2 분
Admin publish crashed with EROFS. Cause: I wrote to disk first, then committed to GitHub. Production fs is read-only.
Why publish-to-live used to take 60s, and how I got it to 3-5s
기술 회고2026년 5월 26일 · 2 분
Production fs is a frozen build snapshot. Reading content through fs.readFile meant 60s of staleness per publish. Moved reads to GitHub Raw.
Hobby photos on a dev portfolio: when they help and when they don't
사용성 회고2026년 5월 26일 · 1 분
I considered a 추억-style photo gallery on /about. Decided against. Kept a small slot for conference/maker/workspace shots only.
Vercel refused to build with next-mdx-remote@5.x (CVE)
트러블슈팅2026년 5월 26일 · 1 분
First production build was blocked by Vercel's security scanner. Solved with a one-line dep bump.
Sidebar width: 16rem felt empty, 13rem felt cramped, 14rem stuck
사용성 회고2026년 5월 26일 · 2 분
The hub layout (left sticky profile / right content) needed two rounds of width tuning before it stopped looking off.
Live site returned 401 to everyone (Vercel Authentication on by default)
트러블슈팅2026년 5월 26일 · 1 분
Production URL was unreachable until I disabled Vercel's default deployment protection. No code change.
Client component pulled node:fs into the browser bundle
트러블슈팅2026년 5월 27일 · 1 분
Vercel build failed with `You may need an additional plugin to handle node: URIs`. LogTimeline.tsx (client) imported lib/logs.ts (server), pulling node:fs into webpack's client bundle.
Cross-repo log aggregation: each repo keeps its own, the portfolio pulls
기술 회고2026년 5월 27일 · 3 분
Added `logSourceRepo` to project frontmatter so each project's log timeline can be fetched from its own separate repo. Pull-on-demand with 30s ISR cache, no polling.
Domain typo: daseon.ai vs daeseon.ai
트러블슈팅2026년 5월 27일 · 1 분
Project was bootstrapped with daseon.ai (one letter short). The real registered domain is daeseon.ai. Found at Vercel domain connection time.
Image upload UX: from a tiny button to a real dropzone
사용성 회고2026년 5월 27일 · 1 분
Admin image upload worked the whole time, but I couldn't reliably find it. Fixed the discoverability instead of the mechanism.
Designing the project-log system (this thing you're reading)
기술 회고2026년 5월 27일 · 3 분
Why I added a fourth content type for project logs, dual-wrote to a machine-facing reference and a human-facing timeline, and built explicit anti-hallucination rules.
Stop hook: from reminder to enforcement (blocking + self-terminating sentinel)
기술 회고2026년 5월 27일 · 3 분
The original Stop hook nudged with a systemMessage, which Claude could ignore. Upgraded to decision:block + reason with a commit-hash sentinel that terminates the loop once a log entry exists.