A new public /docs area covering the whole platform, organized by Diátaxis: tutorials (learning), how-to guides (tasks), reference (facts), and explanation (the why). 29 pages, each grounded in the actual routes, actions, schema, and UI — verified against the code and corrected for accuracy (e.g. admin-only vs admin+board gating, where the permissions matrix actually lives, how Stripe reconciliation matches). Implementation: - lib/docs/nav.ts is the single source of truth (categories + pages), driving the sidebar, static params, and prev/next. - Content authored as content/docs/<category>/<slug>.md, read at build time (the routes are statically generated), rendered by <DocsMarkdown> — reuses the existing react-markdown/GFM stack, no new dependencies. - (docs) route group with its own theme (docs.css) matching the public site's dark / monospace / lime aesthetic; sidebar with active-state, breadcrumb, prev/next, and a Diátaxis home. Public — signed-in users can read it too. - "Docs" link added to the landing nav. typecheck 0 · lint 0 errors · build ok (all /docs pages prerendered)
18 lines
656 B
TypeScript
18 lines
656 B
TypeScript
import { promises as fs } from 'node:fs'
|
|
import path from 'node:path'
|
|
|
|
// Doc bodies are authored as markdown under content/docs/<category>/<slug>.md
|
|
// and read at build time (the /docs routes are statically generated, so the
|
|
// files are only needed during `next build`, never at runtime).
|
|
const CONTENT_ROOT = path.join(process.cwd(), 'content', 'docs')
|
|
|
|
export async function loadDocContent(categoryId: string, slug: string): Promise<string | null> {
|
|
const file = path.join(CONTENT_ROOT, categoryId, `${slug}.md`)
|
|
try {
|
|
const raw = await fs.readFile(file, 'utf8')
|
|
return raw.trim().length > 0 ? raw : null
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|