Skip to content

Latest commit

 

History

History
120 lines (88 loc) · 4.69 KB

File metadata and controls

120 lines (88 loc) · 4.69 KB

Architecture

System Overview

This is a single Next.js 16 app (App Router) that serves both documentation and blog content for the .agent Community. It replaced a Fumadocs monorepo in Feb 2026.

The system has three layers:

content/          Markdown source files (MDX)
    |
src/lib/          Content engine (pure logic, zero React)
    |
src/app/          Next.js routes, renders MDX with custom components
src/components/   React components for layout, sidebar, TOC, etc.

Content Layer

All content lives in content/ as MDX files:

  • content/docs/*.mdx — Documentation pages. Navigation order defined in meta.json.
  • content/blog/YYYY-MM-DD-*.mdx — Blog posts. Sorted by frontmatter date field.

Content files use standard MDX. Custom components (Card, Cards, Callout) are injected at render time — no imports needed in MDX files.

Navigation: meta.json

{
  "title": ".agent Community",
  "pages": ["index", "work-items"]
}
  • "index" maps to content/docs/index.mdx, route /docs
  • Other entries resolve to {name}.mdx or {name}/index.mdx
  • Nested directories can have their own meta.json with a pages array for child nav items

Blog naming convention

Filename: 2026-02-05-why-aid-now-supports-ucp.mdx

  • Date prefix YYYY-MM-DD- is stripped to produce the slug: why-aid-now-supports-ucp
  • Route: /blog/why-aid-now-supports-ucp
  • The frontmatter date field takes precedence over the filename date for sorting

Content Engine (src/lib/)

Pure TypeScript, zero React dependencies. Can be extracted as a standalone package.

File Purpose
types.ts DocPage, BlogPost, Heading, NavItem interfaces
docs.ts getDoc(slug[]), getAllDocSlugs(), getDocNavigation()
blog.ts getPost(slug), getAllPosts(), getAllTags(), getAllPostSlugs()
search.ts getSearchIndex(), search(query) — in-memory substring matching

The content engine reads files from disk using fs and parses frontmatter with gray-matter. Headings are extracted via regex for the table of contents. No caching — filesystem is source of truth.

Rendering Pipeline

MDX is rendered server-side via next-mdx-remote/rsc:

MDX source
  -> remark-gfm (tables, task lists)
  -> rehype-slug (heading IDs)
  -> rehype-autolink-headings (anchor wrapping)
  -> mdx-components.tsx (style overrides, Card/Cards, mermaid detection)
  -> HTML output

Custom MDX components (src/components/mdx-components.tsx) override all HTML elements with Tailwind-styled versions. Mermaid code blocks are detected and routed to a client-side renderer.

Routes

Route Type Description
/ Static Redirects to /docs
/docs SSG Docs landing (catch-all [[...slug]])
/docs/[slug] SSG Individual doc pages
/blog Dynamic Blog index with tag filtering via ?tag=
/blog/[slug] SSG Individual blog posts
/api/search Dynamic Search API (?q=query)
/api/mdx/[...slug] Dynamic Raw MDX export (text/markdown or ?format=json)
/rss.xml Dynamic RSS feed
/sitemap.xml Static Auto-generated from all content
/robots.txt Static Standard robots file
/aid/* Redirect Permanent redirect to aid.agentcommunity.org

Static Assets

  • public/assets/ — Logos (light/dark SVGs)
  • public/og/ — Build-time generated OG images (1200x630 PNG, gitignored)
  • public/blog/ — Blog post images
  • public/favicon.ico

OG images are generated by scripts/generate-og-images.ts using satori + resvg. They run at build time (not runtime), so Vercel serves them as static files with zero function invocations.

SEO

  • metadataBase set in root layout — all relative OG URLs resolve correctly
  • Canonical URLs on every page
  • OpenGraph + Twitter card meta tags with static OG images
  • JSON-LD structured data: Organization + WebSite (root layout)
  • RSS feed linked via <link rel="alternate">
  • Sitemap with all docs + blog URLs

Deployment

Single Vercel project. vercel.json runs pnpm generate:og && pnpm build. No monorepo, no workspaces, no pnpm-workspace.yaml.

Key Design Decisions

  1. No Fumadocs — Custom renderer is simpler for our small content set and gives full control.
  2. Server-side MDXnext-mdx-remote/rsc means zero client JS for content pages.
  3. Static OG images — Built at build time to avoid Vercel function costs.
  4. Reusable lib/ — Content engine has zero React deps for portability.
  5. meta.json navigation — Simple JSON ordering instead of filesystem-order or frontmatter-based nav.
  6. Single app — Blog and docs share layout, theme, search. No multi-zone complexity.