Commit 8c3b2b6
feat: migrate from Next.js to Vite + Nitro (#24)
* feat: remove Next.js deps, add Vite + Nitro stack, delete app router
- Remove next, remark-attr, zod, react-device-detect from deps
- Add vite, nitro, react-router-dom, gray-matter, minisearch, satori
- Add fumadocs remark/rehype plugins (remark-gfm, remark-frontmatter, etc.)
- Delete src/app/ (Next.js App Router), source.config.ts, next.config.mjs
- Replace react-device-detect with navigator.platform check
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add Vite + Nitro server structure, pages, and source rewrite
- src/server/: Nitro route handlers (api/, routes/), SSR catch-all,
vite-config.ts with Nitro + fumadocs-mdx/vite (index: false)
- src/server/api/: health, search, specs, apis-proxy
- src/server/routes/: og, robots.txt, sitemap.xml, llms.txt, [...] SSR
- src/pages/: DocsLayout, DocsPage, ApiLayout, ApiPage, NotFound
- src/lib/source.ts: rewrite with fs/promises + gray-matter + fumadocs-core loader()
- src/lib/head.tsx, page-context.tsx: SSR meta and React context
- src/types/globals.d.ts: Vite build-time constant types
- Add nitro, h3, remark-parse to deps
- Add .gitignore and lint script to chronicle package
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: rewrite CLI commands for Vite/Nitro, remove Next.js scaffolding
- CLI dev/build/start/serve: use Vite programmatic API (no child process)
- CLI init: remove .chronicle/ scaffolding, .next from gitignore
- Remove process.ts (attachLifecycleHandlers), resolveNextCli
- Strip scaffold.ts to detectPackageManager() + getChronicleVersion()
- lib/config.ts: replace env vars with __CHRONICLE_* build-time constants
- cli/utils/config.ts: remove env var fallback from resolveContentDir
- tsconfig.json: remove .source paths and source.config.ts include
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: replace Next.js imports with React Router
- next/link → react-router-dom Link
- next/navigation usePathname → useLocation
- next/navigation useRouter → useNavigate
- next/image → native img tag
- next/font/google → removed (font.ts deleted)
- Remove 'use client' directives (not needed with Vite)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: symlink content into package root, fix SSR + client hydration
- Symlink user's content dir to PACKAGE_ROOT/.content/ before starting
- Vite root stays as package root, content accessible via symlink
- SSR: use renderToPipeableStream for Suspense support
- Client: import MDX via /.content/ symlink path for hydration
- loadPageComponent uses symlink path for Vite module resolution
- openapi.ts: async with fs/promises, resolve specs from project root
- scaffold.ts: fully async (detectPackageManager, getChronicleVersion, linkContent)
- build-cli.ts: externalize all dependencies
- Add __CHRONICLE_PACKAGE_ROOT__ build-time constant
- Graceful fallback when API spec files are missing
- Add data-article-content attribute to default theme Page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: simplify init command to content + config only
Remove package.json creation, dependency installation, and
detectPackageManager/getChronicleVersion usage from init.
Init now only creates content dir, chronicle.yaml, sample MDX, and .gitignore.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: remove unused detectPackageManager and getChronicleVersion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: server-side page API, remove source.ts from client bundle
- Add /api/page/:slug endpoint — returns frontmatter + rendered contentHtml
- page-context.tsx: fetch from /api/page on client navigation instead of
importing source.ts (removes fs/gray-matter from client bundle)
- entry-client.tsx: use SSR content HTML for initial hydration
- Extract renderToHtml utility (shared by catch-all route and page API)
- Fixes buffer/node:fs/promises client warnings
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: MDX import on client, /api/page endpoint, fix duplicate React
- Client imports MDX via /.content/ symlink (matches SSR React tree)
- /api/page/:slug returns frontmatter + relativePath for client navigation
- page-context.tsx: fetch /api/page then import MDX (no source.ts on client)
- entry-client.tsx: import MDX for initial hydration
- Remove render-to-html utility (page API returns path, not HTML)
- Embed relativePath instead of filePath in __PAGE_DATA__
- Add .content to .gitignore
- Remove cacheDir and React alias hacks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: inject CSS and JS assets into SSR HTML head
Use Nitro ?assets=client/ssr virtual imports to collect CSS/JS
assets and inject as <link> tags in HTML <head>.
Fixes unstyled flash on initial page load.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: add .output to gitignore
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: fix production build and entry-server SSR pattern
- build.ts: use createBuilder() + buildApp() for multi-environment build
(client, SSR, Nitro all build correctly)
- entry-server.tsx: rewrite as Nitro server entry with export default { fetch }
using renderToReadableStream, asset injection via ?assets imports
- source.ts: use @content/ alias in import() so Vite bundles MDX at build time
(removes @vite-ignore, fixes ERR_UNKNOWN_FILE_EXTENSION in production)
- source.ts: check file exists before import to prevent crashes
- Remove index.html template (entry-server renders full HTML)
- Remove catch-all route (entry-server handles SSR)
- Remove serverDir from Nitro config (entry-server pattern)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ci: add canary release workflow for PR builds
Publishes canary npm release on every PR commit with version
format 0.1.0-canary.<short-sha> using --tag canary.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve @content alias in Nitro dev SSR worker
- Add @content alias to Nitro config (mirrors Vite resolve.alias)
- Use @content/ alias in loadPageComponent import (works in both
dev via Nitro alias and build via Vite alias)
- Remove @vite-ignore from dynamic imports
- Add fs.access check before import to prevent crashes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use resolveId plugin for @content alias across all Vite environments
resolve.alias doesn't propagate to Nitro's SSR worker fetchModule.
A custom Vite plugin with resolveId hook runs in all environments.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add preserveSymlinks to prevent symlink resolution outside Vite root
Node resolves symlinks to real paths, which may be outside the Vite root.
preserveSymlinks keeps the .content/ symlink path as-is.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use relative ../../.content/ path for MDX imports
Remove @content alias, resolveId plugin, and preserveSymlinks.
Use relative path from source file to .content/ symlink instead.
Vite statically analyzes the ../../.content/ prefix to glob and
bundle all MDX files at build time. Works in both dev and production.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: add remark plugins for callouts and mermaid diagrams
Configure fumadocs-mdx/vite with remark-directive, remarkDirectiveAdmonition,
remarkMdxMermaid, and remarkUnusedDirectives.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add ReactRouterProvider from fumadocs-core, fix remark plugin config
- Wrap app with ReactRouterProvider in both SSR and client entry
- Fix fumadocs-mdx/vite config: pass mdxOptions via defineConfig as default export
- Enables fumadocs-core Link, usePathname, useRouter, search integration
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: replace custom PageTree/TocItem types with fumadocs-core re-exports
- Re-export Root, Node, Item, Folder, Separator from fumadocs-core/page-tree
- Re-export TOCItemType, TableOfContents from fumadocs-core/toc
- Update ThemeLayoutProps/ThemePageProps to use Root instead of PageTree
- Keep custom Frontmatter and Page types (Page.toc now uses TableOfContents)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: use fumadocs loader API directly in source.ts and api-routes.ts
- Remove SourcePage interface and buildPageTree(), use loader().pageTree with order-based sort
- getPages()/getPage() now return fumadocs Page types directly
- loadPageComponent() takes relativePath string instead of SourcePage
- Rename _absolutePath to _relativePath in scanFiles (stored relative path was misnamed)
- buildApiPageTree() returns fumadocs Root instead of custom PageTree
- Update entry-server, entry-client, page-context, sitemap, api route consumers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: update components to use fumadocs-core types and utilities
- breadcrumbs.tsx: use getBreadcrumbItems() from fumadocs-core/breadcrumb
- Toc.tsx: use AnchorProvider + useActiveAnchor from fumadocs-core/toc
- ReadingProgress.tsx: TocItem → TOCItemType
- Layout.tsx: PageTreeItem → Node with type narrowing for Item/Folder
- ChapterNav.tsx: PageTree/PageTreeItem → Root/Node from fumadocs-core/page-tree
- paper/Page.tsx: use flattenTree + getBreadcrumbItems from fumadocs-core
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: add max-width to content images in default and paper themes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: render mermaid code blocks as diagrams
MdxPre detects language-mermaid code blocks and renders
them with the Mermaid component instead of plain code.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: sidebar sorting — root pages before folders, ghost button for details/summary
- Remove fallback to first child order for folders without index page
- Folders without explicit order sort after root pages
- Restyle <details><summary> as inline ghost button with border and hover
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: style raw HTML details/summary via content CSS selectors
Raw HTML <details> in MDX bypasses component mapping, so style
them directly in .content selector using Apsara design tokens.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use import.meta.glob for nested MDX dynamic imports
Vite variable dynamic imports only work one level deep. Nested content
paths like authn/session.mdx failed on client navigation. Use
import.meta.glob to pre-map all .content files for reliable deep imports.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: remove unused __CHRONICLE_PACKAGE_ROOT__ constant
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: pass TOC data from compiled MDX modules to page components
- loadPageModule returns both default component and toc array
- PageData includes toc field (TableOfContents)
- entry-client and page-context extract toc from import.meta.glob modules
- DocsPage uses page.toc instead of hardcoded empty array
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: extract shared mdx-loader and frontmatter helpers
- Create lib/mdx-loader.ts — single import.meta.glob + loadMdxModule()
- Remove duplicate glob/loader from page-context.tsx and entry-client.tsx
- Add extractFrontmatter() and getRelativePath() to source.ts
- Remove duplicate frontmatter reconstruction from entry-server and api/page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: remove unnecessary @ts-expect-error directives
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: output build artifacts to project cwd instead of package dir
Nitro's vercel preset resolves output from rootDir which defaults to
Vite's root (packageRoot). Override output.dir and publicDir via
nitro config to resolve from projectRoot (cwd).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address CodeRabbit review — path traversal, JSON parse, 404 status
- Wrap meta.json parse in try/catch for malformed files
- Reject relativePath with .. segments and validate resolved path stays within contentDir
- Return 404 status for missing doc pages in SSR
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: hydration mismatch and SSR nested path imports
- Pass loadMdx as prop to PageProvider to avoid import.meta.glob in SSR bundle
- Use import.meta.glob in source.ts for SSR nested MDX imports
- Skip Tabs SSR to avoid Radix useId mismatch (ClientOnly wrapper)
- Add path traversal guard and meta.json parse safety
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* revert: remove mdx-loader.ts, restore inline import.meta.glob
Extracting import.meta.glob to a shared module caused hydration
mismatch — SSR and client Vite environments compiled MDX differently.
Restore inline globs in entry-client.tsx (client-only) and source.ts
(SSR-only) to keep each environment's compilation isolated.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: replace runtime fs calls with build-time data for serverless compatibility
Runtime fs.readdir/readFile calls break on Vercel serverless where content
files don't exist in the function bundle. Replace with import.meta.glob
(build-time) for page tree and baked-in config for chronicle.yaml.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* revert: remove canary build GitHub Action
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove conditional useMemo hook in SidebarNode
useMemo was called after early returns, violating Rules of Hooks.
Replaced with plain JSX since memoization is unnecessary here.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: strip .md/.mdx extensions from internal links in MDX content
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: treat README.md/README.mdx as folder index pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: suppress nitro preview message, show chronicle start hint after build
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: force light theme for paper theme, disable dark mode
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent c959147 commit 8c3b2b6
86 files changed
Lines changed: 2541 additions & 1883 deletions
File tree
- packages/chronicle
- src
- app
- [[...slug]]
- apis/[[...slug]]
- api
- apis-proxy
- health
- search
- llms-full.txt
- llms.txt
- og
- cli
- commands
- utils
- components
- mdx
- ui
- lib
- pages
- server
- api
- page
- routes
- utils
- themes
- default
- paper
- types
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
8 | | - | |
| 8 | + | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | | - | |
12 | | - | |
| 12 | + | |
| 13 | + | |
13 | 14 | | |
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | | - | |
14 | 12 | | |
15 | 13 | | |
16 | 14 | | |
17 | 15 | | |
18 | 16 | | |
19 | 17 | | |
20 | | - | |
| 18 | + | |
| 19 | + | |
21 | 20 | | |
22 | 21 | | |
23 | 22 | | |
| |||
37 | 36 | | |
38 | 37 | | |
39 | 38 | | |
40 | | - | |
41 | | - | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
48 | 51 | | |
49 | 52 | | |
50 | | - | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
51 | 56 | | |
52 | | - | |
53 | 57 | | |
54 | | - | |
| 58 | + | |
55 | 59 | | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
56 | 65 | | |
57 | 66 | | |
58 | 67 | | |
59 | | - | |
60 | | - | |
61 | | - | |
| 68 | + | |
| 69 | + | |
62 | 70 | | |
63 | 71 | | |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
0 commit comments