The documentation site for the Solar Shading Estimator API — a Fumadocs + Next.js site that renders API reference pages generated directly from the API's OpenAPI spec, alongside hand-written guides.
Rather than maintaining API reference docs by hand, this site fetches the live OpenAPI schema from the API itself and generates per-operation MDX pages from it, so the reference docs stay in sync with the actual API without manual upkeep.
Hand-written API references drift out of date as endpoints change. This site pulls the OpenAPI spec straight from the deployed API and regenerates the reference pages from it, so "what's documented" and "what's deployed" don't diverge.
| Layer | What |
|---|---|
| Framework | Next.js 16 (App Router) |
| Runtime | Bun (primary), Node.js |
| Language | TypeScript |
| Docs framework | Fumadocs with Fumadocs MDX collections |
| OpenAPI generation | fumadocs-openapi |
| Styling | Tailwind CSS v4 + PostCSS + tw-animate-css + tailwind-merge |
| UI components | shadcn/ui + Base UI + Lucide icons |
| Linting / formatting | Biome |
| Env validation | @t3-oss/env-nextjs + Valibot |
| Error monitoring | Sentry |
| Analytics | Vercel Analytics + Speed Insights |
| Git hooks | Husky + commitlint + lint-staged |
| Testing | bun test |
| Deployment | Vercel |
The reference pages aren't written by hand — they're generated from the API's OpenAPI spec via a script (scripts/generate-docs.ts) that:
- Fetches the OpenAPI spec from the live API (
API_URL/openapi.json), retrying up to 5 times with a delay between attempts in case the API is asleep (Render free tier) or briefly unavailable. - Runs
fumadocs-openapi'sgenerateFiles()against that spec, writing one MDX page per operation intocontent/docs/api-reference, grouped by OpenAPI tag, with frontmatter (title/description) derived from each operation. - Syncs the root sidebar (
content/docs/meta.json) so an "API Reference" section pointing at the generated pages is kept up to date, while preserving any other hand-authored sidebar entries.
In production, a failed spec fetch (after all retries) is reported to Sentry rather than crashing the build silently; in development it just logs to the console.
Re-run this generation step whenever the API's OpenAPI spec changes, so the reference pages pick up new/changed endpoints.
| Path | Description |
|---|---|
lib/source.ts |
Content source adapter — loader() provides the content API. |
lib/layout.shared.tsx |
Shared layout options. |
lib/openapi.ts |
Configures the OpenAPI source and fetches the live spec. |
lib/shared.ts |
Shared route helpers. |
lib/cn.ts |
cn() utility (class-variance-authority + tailwind-merge). |
lib/errors.ts |
Error-class helpers for structured failure handling. |
scripts/generate-docs.ts |
The spec-fetch + MDX generation script. |
proxy.ts |
Fumadocs content-negotiation proxy middleware. |
env/ |
Client/server/shared env schemas with Valibot validation. |
instrumentation.ts |
Next.js instrumentation — registers Sentry. |
app/(home) |
Route group for the landing page. |
app/docs |
Documentation layout and pages. |
app/api/search/route.ts |
Route handler for search. |
content/docs/api-reference |
Generated API reference pages — do not edit directly. |
source.config.ts |
Fumadocs MDX config — frontmatter schemas and collection options. |
bun install
bun run devOr with npm / pnpm:
npm install
npm run devpnpm install
pnpm devOpen http://localhost:3000 to see the result.
bun run generate:docsRequires API_URL to point at a running instance of the API. This is also wired into predev and prebuild, so it runs automatically before the dev server or production build.
- No content editing UI. MDX guides are written and edited directly in the repo.
- Reference pages are generated, not hand-written. Editing files under
content/docs/api-referencedirectly will be overwritten the next time the generation script runs — change the API's OpenAPI spec (or annotations that produce it) instead. - No authentication. The site is public, matching the API's current single-user/demo scope.
- Spec freshness depends on the API being reachable. If the API is asleep (Render free tier) or unreachable at generation time, generation retries for a bit and then fails — it doesn't fall back to a stale cached spec.
- Next.js Documentation — Next.js features and API.
- Fumadocs — the docs framework powering this site.
fumadocs-openapi— OpenAPI reference generation.- Biome — linter and formatter.
- Valibot — schema validation library.
MIT — see LICENSE.