Skip to content

Latest commit

 

History

History
139 lines (103 loc) · 5.13 KB

File metadata and controls

139 lines (103 loc) · 5.13 KB

ARCHITECTURE

Last updated: 2026-05-07

System Summary

eunu.log is a Next.js App Router blog platform with:

  • File-based MDX content under posts/**.
  • Static generation for blog routes.
  • Server-side view counting via Supabase RPC.
  • Client-side analytics via Umami trackers.
  • Token-driven UI styling (Tailwind + CSS variables).

Runtime Topology

Web Runtime

  • Framework: Next.js (next@16.1.4) with App Router.
  • React: react@19.2.3.
  • Rendering mix:
    • Static prerendered route params via generateStaticParams for post pages.
    • Server route handlers for feed and OG image.
    • Domain-owned server actions for view counting.

Edge Runtime

  • src/app/api/og/route.tsx runs at the edge and returns social images via ImageResponse.

High-Level Modules

App Layer (src/app)

  • layout.tsx composes global providers, metadata, JSON-LD, analytics, and dual roots (#app-root, #overlay-root).
  • Main pages:
    • / home (src/app/page.tsx)
    • /blog listing (src/app/blog/page.tsx)
    • /blog/[slug] post detail (src/app/blog/[slug]/page.tsx)
    • /resume and /series
  • Route handlers:
    • /feed.xml (src/app/feed.xml/route.ts)
    • /api/og (src/app/api/og/route.tsx)
  • src/app imports page adapters from top-level domain modules and does not own domain policy.

Content Layer (posts/** + blog/services)

  • blog/services/post-repository.ts recursively discovers valid post folders (index.mdx + meta.json).
  • meta.json is validated with Zod (FeedFrontmatterSchema).
  • MDX is loaded by dynamic import per folder path.
  • Reading time is auto-derived from MDX when metadata omits it.
  • Slug-to-folder cache accelerates lookups.

Markdown/MDX Processing

  • Custom webpack rule in next.config.mjs for .mdx with:
    • remark-gfm
    • rehype-slug
    • rehype-pretty-code
  • blog/services/markdown-parser.ts parses MDX headings for TOC data.
  • blog/ui/mdx/components.tsx maps MDX nodes to UI components and interactive visualization widgets.

Domain-first Modular Monolith

  • blog/: post schema, repository, publication policy, series, blog UI, view-count use case.
  • resume/: resume data, ordering, resume UI.
  • search/: command palette, search action, search recommendation.
  • site/: home composition, AppShell, navigation, providers, site config.
  • platform/: Supabase integration, Umami analytics, SEO helper, devtools.
  • shared/: domain-agnostic UI, layout primitive, motion helper, testing helper, visualization widget.
  • styles/: design tokens, global base styles, local font CSS.
  • Theming via next-themes provider in site/providers.

Data and Integrations

  • Supabase client setup in platform/integrations/supabase.ts.
  • View count data model:
    • table: public.views
    • rpc: increment_view(slug_input text) -> bigint
  • SQL provisioning script: docs/database/supabase-view-count.sql.

Analytics and SEO

  • Umami event helpers in platform/analytics/lib/analytics.ts.
  • Trackers in platform/analytics/components/*.
  • Structured data via JsonLd component in layout and post page.

Request/Data Flows

Blog Post Render Flow

  1. generateStaticParams() builds route list from posts metadata.
  2. Request to /blog/[slug] resolves post via getFeedData(slug).
  3. MDX source is parsed for heading structure (TOC).
  4. MDX component renders with mapped custom components.
  5. Client tracker records post view; blog/api/view.ts can persist counter in Supabase.

Feed Flow

  1. /feed.xml route reads sorted metadata.
  2. XML string is generated server-side.
  3. Response is cached with s-maxage=3600.

View Count Flow

  1. Client triggers view tracking.
  2. Server action normalizes slug and calls Supabase RPC.
  3. RPC upserts/increments views.count.
  4. Latest count is returned/fetched.

Testing and Quality

  • Unit/component tests: Vitest + Testing Library across top-level modules and src/app.
  • E2E tests: Playwright mobile-focused projects (tests/e2e/**/*.spec.ts).
  • Linting/formatting: ESLint, Prettier, markdownlint, cspell.
  • Coverage focus includes blog, resume, search, site, platform, shared, styles, and selected route adapters.

Current Architecture Risks

  1. Docs/runtime drift:
    • AGENTS and README mention older stack assumptions; package versions are newer.
  2. Provider boundary drift:
    • Route/layout changes can reintroduce duplicated tracker mounts if AppProviders is bypassed.
  3. Boundary enforcement drift:
    • Module boundaries are physical and documented, but lint-level enforcement is not yet configured.
  4. SEO endpoint mismatch risk:
    • Post JSON-LD image URL differs from the actual OG route path/domain conventions.

Decisions to Preserve

복원한 아키텍처 결정의 상세 기록은 docs/adr/README.md에 둔다.

  1. Keep folder-based content (posts/**) with meta.json + index.mdx.
  2. Keep Zod schema validation in content ingestion path.
  3. Keep token-first styling and avoid one-off visual constants where possible.
  4. Keep route-level separation for feed, OG, and view-count concerns.
  5. Keep Umami analytics separate from Supabase-backed public view counts.
  6. Keep top-level domain modules as documented in ADR 0011.