@prudentbird/voxx 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/index.mjs +9 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/templates/blog/layout.tsx.tpl +1 -1
- package/templates/blog/post-page.tsx.tpl +13 -0
- package/templates/changelog/layout.tsx.tpl +1 -1
- package/templates/docs/layout-root.tsx.tpl +1 -1
- package/templates/docs/layout.tsx.tpl +1 -1
- package/templates/shared/robots.ts.tpl +5 -1
- package/templates/shared/sitemap.ts.tpl +9 -2
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
A zero-friction CMS for you and your agents. Write markdown the way you ship code, and Voxx handles the rest.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
npx voxx init # scaffold a blog into your Next.js app
|
|
7
|
-
npx voxx init docs # or a docs site
|
|
8
|
-
npx voxx init changelog # or a release-notes page
|
|
6
|
+
npx @prudentbird/voxx init # scaffold a blog into your Next.js app
|
|
7
|
+
npx @prudentbird/voxx init docs # or a docs site
|
|
8
|
+
npx @prudentbird/voxx init changelog # or a release-notes page
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Commands
|
package/dist/index.mjs
CHANGED
|
@@ -596,7 +596,7 @@ async function init(argv) {
|
|
|
596
596
|
} else if (!hasNext) {
|
|
597
597
|
log.warn("No Next.js detected — wrote voxx.json + sample content only.");
|
|
598
598
|
log.info(` Install the engine: ${c.cyan("npm i @prudentbird/voxx-core")}`);
|
|
599
|
-
log.info(` Or build static HTML: ${c.cyan("npx voxx build")}`);
|
|
599
|
+
log.info(` Or build static HTML: ${c.cyan("npx @prudentbird/voxx build")}`);
|
|
600
600
|
} else if (!appDir) log.warn("Next.js found but no app/ directory — pass --app <dir> to scaffold routes.");
|
|
601
601
|
else {
|
|
602
602
|
let step = 1;
|
|
@@ -643,7 +643,7 @@ ${opts.body}
|
|
|
643
643
|
`;
|
|
644
644
|
}
|
|
645
645
|
function siteHeader(config) {
|
|
646
|
-
const base = config.
|
|
646
|
+
const base = config.site.titleHref ?? "/";
|
|
647
647
|
const rss = config.features.rss ? `<div class="voxx-header__actions"><a class="voxx-icon-button" href="${escapeXml(rssPath(config))}" aria-label="RSS feed"><svg viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><circle cx="5" cy="19" r="1" fill="currentColor"/></svg></a></div>` : "";
|
|
648
648
|
return ` <header class="voxx voxx-header">
|
|
649
649
|
<a class="voxx-header__title" href="${escapeXml(base)}">${escapeXml(config.site.title)}</a>
|
|
@@ -686,10 +686,14 @@ ${posts.map((post) => {
|
|
|
686
686
|
${cards}
|
|
687
687
|
</main>`;
|
|
688
688
|
}
|
|
689
|
+
function backLink(config) {
|
|
690
|
+
return `<a class="voxx-article__back" href="${escapeXml(config.content.basePath || "/")}"><svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M10 12 6 8l4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>All posts</a>`;
|
|
691
|
+
}
|
|
689
692
|
function postBody(post, config) {
|
|
690
693
|
const aside = config.features.toc ? tocAside(post) : "";
|
|
691
694
|
return ` <main class="voxx voxx-layout">
|
|
692
695
|
<article class="voxx-article">
|
|
696
|
+
${backLink(config)}
|
|
693
697
|
<header class="voxx-article__header">
|
|
694
698
|
<h1>${escapeXml(post.title)}</h1>
|
|
695
699
|
<p class="voxx-article__meta">${metaLine(post, config)}</p>
|
|
@@ -714,7 +718,7 @@ function pagerHtml(prev, next) {
|
|
|
714
718
|
</nav>`;
|
|
715
719
|
}
|
|
716
720
|
function docsSidebar(nav, activeUrl, config) {
|
|
717
|
-
const base = config.
|
|
721
|
+
const base = config.site.titleHref ?? "/";
|
|
718
722
|
return `<aside class="voxx-docs__nav"><div class="voxx-docs__nav-inner">
|
|
719
723
|
<div class="voxx-docs__nav-header">
|
|
720
724
|
<details class="voxx-docs__menu"><summary aria-label="Navigation"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M9 3v18"/></svg></summary>
|
|
@@ -934,6 +938,8 @@ async function build(argv) {
|
|
|
934
938
|
});
|
|
935
939
|
const { config } = result;
|
|
936
940
|
if (!config.site.url || /example\.com/.test(config.site.url)) log.warn(`site.url is ${config.site.url ? `"${config.site.url}"` : "empty"} — feeds, sitemap, and SEO tags need the real production URL in voxx.json.`);
|
|
941
|
+
const servesRoot = config.collections.some((col) => stripLead(col.basePath) === "");
|
|
942
|
+
if (config.site.titleHref === void 0 && !servesRoot) log.warn(`The title link defaults to "/", but nothing is generated there (no collection uses basePath "/"). Set site.titleHref in voxx.json — e.g. "${config.collections[0].basePath}" to point at the index, or your parent site's home if this is embedded under a larger site.`);
|
|
937
943
|
const type = config.content.type;
|
|
938
944
|
const noun = type === "changelog" ? "release" : type === "docs" ? "page" : "post";
|
|
939
945
|
const what = result.collectionCount > 1 ? `${result.pageCount} pages across ${result.collectionCount} collections` : `${result.pageCount} ${noun}${result.pageCount === 1 ? "" : "s"}`;
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["esc"],"sources":["../src/util.ts","../src/commands/init.ts","../src/commands/build.ts","../src/commands/dev.ts","../src/commands/new.ts","../src/index.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { access, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst require = createRequire(import.meta.url);\nconst TEMPLATES_DIR = fileURLToPath(new URL(\"../templates\", import.meta.url));\n\nconst useColor = process.stdout.isTTY && !process.env[\"NO_COLOR\"];\nconst wrap = (code: string) => (s: string) =>\n useColor ? `[${code}m${s}[0m` : s;\n\n/** ANSI color helpers that degrade gracefully in non-TTY environments. */\nexport const c = {\n bold: wrap(\"1\"),\n dim: wrap(\"2\"),\n red: wrap(\"31\"),\n green: wrap(\"32\"),\n yellow: wrap(\"33\"),\n cyan: wrap(\"36\"),\n};\n\n/** Prefixed console helpers used throughout the CLI commands. */\nexport const log = {\n info: (msg: string) => console.log(msg),\n success: (msg: string) => console.log(`${c.green(\"✓\")} ${msg}`),\n warn: (msg: string) => console.log(`${c.yellow(\"!\")} ${msg}`),\n error: (msg: string) => console.error(`${c.red(\"✗\")} ${msg}`),\n};\n\n/**\n * Returns `true` if the path exists and is accessible, `false` otherwise.\n */\nexport async function exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Reads a scaffold template file by name from the bundled `templates/` directory.\n *\n * @param name - Template filename, e.g. `\"shared/data.ts.tpl\"`.\n */\nexport async function readTemplate(name: string): Promise<string> {\n return readFile(join(TEMPLATES_DIR, name), \"utf8\");\n}\n\n/**\n * Replaces `{{KEY}}` placeholders in a template string.\n *\n * @param tpl - Template string containing `{{VARIABLE}}` tokens.\n * @param vars - Map of token names to replacement values.\n */\nexport function render(tpl: string, vars: Record<string, string> = {}): string {\n return tpl.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => vars[key] ?? \"\");\n}\n\n/** Result of a `writeFileSafe` call. */\nexport type WriteStatus = \"written\" | \"skipped\";\n\n/**\n * Writes `content` to `path`, creating parent directories as needed.\n * Skips the write if the file already exists and `force` is `false`.\n *\n * @param path - Destination file path.\n * @param content - File content to write.\n * @param force - Overwrite existing files when `true`. Defaults to `false`.\n * @returns `\"written\"` if the file was created/replaced, `\"skipped\"` if it already existed.\n */\nexport async function writeFileSafe(\n path: string,\n content: string,\n force = false,\n): Promise<WriteStatus> {\n await mkdir(dirname(path), { recursive: true });\n if (!force && (await exists(path))) return \"skipped\";\n await writeFile(path, content);\n return \"written\";\n}\n\n/**\n * Resolves the path to a sub-asset of the installed `@prudentbird/voxx-core` package.\n *\n * @param subpath - Package-relative path, e.g. `\"theme/voxx.css\"`.\n */\nexport function resolveCoreAsset(subpath: string): string {\n return require.resolve(`@prudentbird/voxx-core/${subpath}`);\n}\n\n/**\n * Converts a package name or slug to Title Case.\n *\n * Strips any npm scope prefix (`@scope/`) before converting.\n */\nexport function titleCase(name: string): string {\n return name\n .replace(/^@[^/]+\\//, \"\")\n .replace(/[-_]+/g, \" \")\n .replace(/\\b\\w/g, (m) => m.toUpperCase())\n .trim();\n}\n\n/**\n * Returns `true` if the path is a safe relative path that stays within the\n * project root (no absolute paths, no `..` traversal, no null bytes).\n */\nexport function isSafeRelPath(p: string): boolean {\n if (p === \"\") return true;\n if (p.includes(\"\\0\")) return false;\n if (p.startsWith(\"/\") || /^[A-Za-z]:[\\\\/]/.test(p)) return false;\n return p.split(/[\\\\/]/).every((seg) => seg !== \"..\");\n}\n\n/**\n * Normalizes a URL base path to always have a leading slash and no trailing slash.\n *\n * @param base - Raw base path, e.g. `\"blog/\"` or `\"/blog\"`.\n * @returns Normalized path, e.g. `\"/blog\"`.\n */\nexport function normalizeBase(base: string): string {\n const withLead = base.startsWith(\"/\") ? base : `/${base}`;\n return withLead.length > 1 ? withLead.replace(/\\/+$/, \"\") : withLead;\n}\n\nconst YAML_PLAIN_RE = /^[A-Za-z0-9](?:[A-Za-z0-9 ._/()-]*[A-Za-z0-9._/()-])?$/;\n\n/**\n * Returns a YAML-safe representation of `value`.\n *\n * Plain strings that match the safe character set are returned as-is;\n * everything else is JSON-quoted.\n */\nexport function yamlValue(value: string): string {\n return YAML_PLAIN_RE.test(value) ? value : JSON.stringify(value);\n}\n","import { spawn } from \"node:child_process\";\nimport { copyFile, mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { parseArgs } from \"node:util\";\nimport {\n DEFAULT_CONFIG,\n resolveCollectionDefaults,\n type CollectionInput,\n} from \"@prudentbird/voxx-core\";\nimport {\n c,\n exists,\n isSafeRelPath,\n log,\n normalizeBase,\n readTemplate,\n render,\n resolveCoreAsset,\n titleCase,\n writeFileSafe,\n type WriteStatus,\n} from \"../util\";\n\nconst APP_DIR_CANDIDATES = [\"app\", \"src/app\"];\nconst GLOBALS_CANDIDATES = [\n \"app/globals.css\",\n \"src/app/globals.css\",\n \"styles/globals.css\",\n \"src/styles/globals.css\",\n \"app/global.css\",\n];\n\nconst PRESETS = [\"blog\", \"docs\", \"changelog\"] as const;\ntype Preset = (typeof PRESETS)[number];\n\nconst PRESET_DEFAULTS: Record<Preset, { title: string; description: string }> =\n {\n blog: { title: \"My Blog\", description: \"A blog built with Voxx.\" },\n docs: { title: \"My Docs\", description: \"Documentation built with Voxx.\" },\n changelog: {\n title: \"Changelog\",\n description: \"Release notes built with Voxx.\",\n },\n };\n\ntype Pkg = {\n name?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n};\n\nasync function readPkg(cwd: string): Promise<Pkg> {\n if (await exists(join(cwd, \"package.json\"))) {\n return JSON.parse(await readFile(join(cwd, \"package.json\"), \"utf8\"));\n }\n return {};\n}\n\nfunction pkgHasNext(pkg: Pkg): boolean {\n return Boolean(pkg.dependencies?.[\"next\"] ?? pkg.devDependencies?.[\"next\"]);\n}\n\nasync function detectAppDir(cwd: string): Promise<string | null> {\n for (const dir of APP_DIR_CANDIDATES) {\n if (await exists(join(cwd, dir))) return dir;\n }\n return null;\n}\n\nasync function detectTokens(cwd: string): Promise<boolean> {\n for (const rel of GLOBALS_CANDIDATES) {\n const path = join(cwd, rel);\n if (await exists(path)) {\n const css = await readFile(path, \"utf8\");\n if (css.includes(\"--background\") || css.includes(\"--foreground\"))\n return true;\n }\n }\n return false;\n}\n\nasync function copyAsset(\n subpath: string,\n target: string,\n force: boolean,\n): Promise<WriteStatus> {\n if (!force && (await exists(target))) return \"skipped\";\n await mkdir(dirname(target), { recursive: true });\n await copyFile(resolveCoreAsset(subpath), target);\n return \"written\";\n}\n\nfunction run(cmd: string, args: string[], cwd: string): Promise<number> {\n return new Promise((resolve, reject) => {\n const child = spawn(cmd, args, { cwd, stdio: \"inherit\" });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolve(code ?? 1));\n });\n}\n\nasync function chooseSetup(): Promise<\"static\" | \"next\"> {\n if (!process.stdin.isTTY) return \"static\";\n\n log.warn(\"No Next.js app detected here.\");\n log.info(\n ` ${c.cyan(\"1.\")} Static site — markdown in, HTML/CSS out via ${c.cyan(\"voxx build\")}`,\n );\n log.info(\n ` ${c.cyan(\"2.\")} New Next.js app — runs ${c.cyan(\"create-next-app\")}, then scaffolds`,\n );\n\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n for (;;) {\n const answer = (await rl.question(`Choose [1/2] (default 1): `)).trim();\n if (answer === \"\" || answer === \"1\") return \"static\";\n if (answer === \"2\") return \"next\";\n log.warn(\"Please answer 1 or 2.\");\n }\n } finally {\n rl.close();\n }\n}\n\nasync function createNextApp(cwd: string): Promise<string | null> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n let dir: string;\n try {\n dir =\n (\n await rl.question(\n `Directory for the new app (default ${c.cyan(\"my-app\")}): `,\n )\n ).trim() || \"my-app\";\n } finally {\n rl.close();\n }\n\n log.info(\"\");\n const code = await run(\"npx\", [\"create-next-app@latest\", dir], cwd);\n if (code !== 0) {\n log.error(\"create-next-app failed — nothing scaffolded.\");\n return null;\n }\n return join(cwd, dir);\n}\n\nasync function isolateCreatedApp(\n cwd: string,\n appDir: string,\n): Promise<boolean> {\n const siteDir = join(cwd, appDir, \"(site)\");\n const moved: string[] = [];\n for (const file of [\n \"layout.tsx\",\n \"layout.js\",\n \"page.tsx\",\n \"page.js\",\n \"page.module.css\",\n ]) {\n const from = join(cwd, appDir, file);\n if (!(await exists(from))) continue;\n await mkdir(siteDir, { recursive: true });\n await rename(from, join(siteDir, file));\n moved.push(file);\n }\n if (!moved.some((f) => f.startsWith(\"layout.\"))) return false;\n for (const file of [\"layout.tsx\", \"layout.js\"]) {\n const path = join(siteDir, file);\n if (!(await exists(path))) continue;\n const src = await readFile(path, \"utf8\");\n await writeFile(path, src.replace('\"./globals.css\"', '\"../globals.css\"'));\n }\n return true;\n}\n\nconst NEXT_CONFIG_FILES = [\n \"next.config.ts\",\n \"next.config.mjs\",\n \"next.config.js\",\n \"next.config.cjs\",\n];\n\nfunction nextMajor(pkg: Pkg): number | null {\n const range =\n pkg.dependencies?.[\"next\"] ?? pkg.devDependencies?.[\"next\"] ?? \"\";\n const m = /(\\d+)/.exec(range);\n return m ? Number(m[1]) : null;\n}\n\nconst MINIMAL_NEXT_CONFIG = `import type { NextConfig } from \"next\";\n\nconst nextConfig: NextConfig = {\n cacheComponents: true,\n};\n\nexport default nextConfig;\n`;\n\ntype CacheComponentsResult =\n | { kind: \"enabled\" | \"created\" | \"already\"; file: string }\n | { kind: \"manual\" | \"unsupported\" };\n\nasync function enableCacheComponents(\n cwd: string,\n pkg: Pkg,\n): Promise<CacheComponentsResult> {\n const major = nextMajor(pkg);\n if (major !== null && major < 16) return { kind: \"unsupported\" };\n\n let file: string | null = null;\n for (const name of NEXT_CONFIG_FILES) {\n if (await exists(join(cwd, name))) {\n file = name;\n break;\n }\n }\n\n if (!file) {\n if (major === null) return { kind: \"manual\" };\n await writeFile(join(cwd, \"next.config.ts\"), MINIMAL_NEXT_CONFIG);\n return { kind: \"created\", file: \"next.config.ts\" };\n }\n\n const source = await readFile(join(cwd, file), \"utf8\");\n if (/\\bcacheComponents\\b/.test(source)) return { kind: \"already\", file };\n\n const m =\n /(const\\s+nextConfig\\s*(?::\\s*[\\w.]+)?\\s*=\\s*|export\\s+default\\s+|module\\.exports\\s*=\\s*)\\{/.exec(\n source,\n );\n if (!m) return { kind: \"manual\" };\n\n const at = m.index + m[0].length;\n const rest = source.slice(at);\n const insert = rest.trimStart().startsWith(\"}\")\n ? \"\\n cacheComponents: true,\\n\"\n : \"\\n cacheComponents: true,\";\n await writeFile(join(cwd, file), source.slice(0, at) + insert + rest);\n return { kind: \"enabled\", file };\n}\n\ntype RawConfig = Record<string, unknown>;\n\ntype AddPlan =\n | {\n ok: true;\n out: RawConfig;\n name: string;\n dir: string;\n basePath: string;\n }\n | { ok: false; message: string };\n\nfunction planAdd(\n raw: RawConfig,\n preset: Preset,\n values: { name?: string; dir?: string; base?: string },\n): AddPlan {\n const rawCollections = Array.isArray(raw[\"collections\"])\n ? (raw[\"collections\"] as CollectionInput[])\n : [];\n const rawContent = (raw[\"content\"] ?? undefined) as\n | CollectionInput\n | undefined;\n\n const existing =\n rawCollections.length > 0\n ? rawCollections.map(resolveCollectionDefaults)\n : [\n {\n name: rawContent?.type ?? DEFAULT_CONFIG.content.type,\n type: rawContent?.type ?? DEFAULT_CONFIG.content.type,\n dir: rawContent?.dir ?? DEFAULT_CONFIG.content.dir,\n basePath: rawContent?.basePath ?? DEFAULT_CONFIG.content.basePath,\n drafts: rawContent?.drafts ?? false,\n },\n ];\n const first = existing[0]!;\n\n const name = values.name ?? preset;\n const dir = values.dir ?? `content/${name}`;\n const basePath = normalizeBase(values.base ?? `/${name}`);\n\n if (existing.some((c) => c.name === name)) {\n return {\n ok: false,\n message: `Collection \"${name}\" already exists — defined: ${existing\n .map((c) => c.name)\n .join(\", \")}. Pass --name <other>.`,\n };\n }\n const dupBase = existing.find((c) => c.basePath === basePath);\n if (dupBase) {\n return {\n ok: false,\n message: `Base path \"${basePath}\" is already used by collection \"${dupBase.name}\" — pass --base <path>.`,\n };\n }\n const dupDir = existing.find((c) => c.dir === dir);\n if (dupDir) {\n return {\n ok: false,\n message: `Content dir \"${dir}\" is already used by collection \"${dupDir.name}\" — pass --dir <dir>.`,\n };\n }\n\n const next = { name, type: preset, dir, basePath, drafts: false };\n\n if (rawCollections.length > 0) {\n return {\n ok: true,\n out: { ...raw, collections: [...rawCollections, next] },\n name,\n dir,\n basePath,\n };\n }\n\n const migrated: Record<string, unknown> = {\n name: first.name,\n ...(rawContent ?? {}),\n };\n const reResolved = resolveCollectionDefaults(migrated as CollectionInput);\n if (reResolved.dir !== first.dir) migrated[\"dir\"] = first.dir;\n if (reResolved.basePath !== first.basePath) {\n migrated[\"basePath\"] = first.basePath;\n }\n\n const collections = [migrated, next];\n const out: RawConfig = {};\n let inserted = false;\n for (const [key, value] of Object.entries(raw)) {\n if (key === \"content\" || key === \"collections\") {\n if (!inserted) {\n out[\"collections\"] = collections;\n inserted = true;\n }\n continue;\n }\n out[key] = value;\n }\n if (!inserted) out[\"collections\"] = collections;\n\n return { ok: true, out, name, dir, basePath };\n}\n\nexport async function init(argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n dir: { type: \"string\" },\n base: { type: \"string\" },\n app: { type: \"string\" },\n name: { type: \"string\" },\n add: { type: \"boolean\" },\n force: { type: \"boolean\" },\n },\n allowPositionals: true,\n });\n\n const presetArg = positionals[0] ?? \"blog\";\n if (!(PRESETS as readonly string[]).includes(presetArg)) {\n log.error(\n `Unknown preset \"${presetArg}\" — expected one of: ${PRESETS.join(\", \")}.`,\n );\n process.exitCode = 1;\n return;\n }\n const preset = presetArg as Preset;\n const add = Boolean(values.add);\n const force = Boolean(values.force);\n\n if (add && force) {\n log.error(\n \"--add and --force cannot be combined — --add never overwrites. Delete the collection's files and re-run if you need a clean re-scaffold.\",\n );\n process.exitCode = 1;\n return;\n }\n if (!add && values.name !== undefined) {\n log.error(\"--name only applies with --add.\");\n process.exitCode = 1;\n return;\n }\n\n if (values.dir !== undefined && !isSafeRelPath(values.dir)) {\n log.error(\n `Invalid --dir \"${values.dir}\" — must stay within the project (no \"..\").`,\n );\n process.exitCode = 1;\n return;\n }\n if (values.app !== undefined && !isSafeRelPath(values.app)) {\n log.error(\n `Invalid --app \"${values.app}\" — must stay within the project (no \"..\").`,\n );\n process.exitCode = 1;\n return;\n }\n if (values.base !== undefined && values.base.split(/[\\\\/]/).includes(\"..\")) {\n log.error(`Invalid --base \"${values.base}\" — must not contain \"..\".`);\n process.exitCode = 1;\n return;\n }\n\n let cwd = process.cwd();\n let contentDir = values.dir ?? \"content\";\n let basePath = normalizeBase(values.base ?? `/${preset}`);\n let collectionName: string = preset;\n\n let pkg = await readPkg(cwd);\n let hasNext = pkgHasNext(pkg);\n let createdAppDir: string | null = null;\n let staticChoice = false;\n\n const results: Array<\n [label: string, status: WriteStatus, siteWide?: boolean]\n > = [];\n\n if (add) {\n const cfgPath = join(cwd, \"voxx.json\");\n if (!(await exists(cfgPath))) {\n log.error(\n `--add requires an existing voxx.json — run ${c.cyan(`voxx init ${preset}`)} first.`,\n );\n process.exitCode = 1;\n return;\n }\n let raw: RawConfig;\n try {\n raw = JSON.parse(await readFile(cfgPath, \"utf8\")) as RawConfig;\n } catch {\n log.error(\"voxx.json is not valid JSON — fix it before running --add.\");\n process.exitCode = 1;\n return;\n }\n const plan = planAdd(raw, preset, values);\n if (!plan.ok) {\n log.error(plan.message);\n process.exitCode = 1;\n return;\n }\n collectionName = plan.name;\n contentDir = plan.dir;\n basePath = plan.basePath;\n await writeFile(cfgPath, `${JSON.stringify(plan.out, null, 2)}\\n`);\n results.push([\n `voxx.json (added collection \"${collectionName}\")`,\n \"written\",\n ]);\n } else if (!hasNext) {\n const setup = await chooseSetup();\n if (setup === \"next\") {\n createdAppDir = await createNextApp(cwd);\n if (!createdAppDir) {\n process.exitCode = 1;\n return;\n }\n cwd = createdAppDir;\n pkg = await readPkg(cwd);\n hasNext = pkgHasNext(pkg);\n } else {\n staticChoice = true;\n }\n }\n\n const baseSegment = basePath.slice(1);\n const appDir = values.app ?? (await detectAppDir(cwd));\n const siteTitle = pkg.name\n ? titleCase(pkg.name)\n : PRESET_DEFAULTS[preset].title;\n\n if (!add) {\n results.push([\n \"voxx.json\",\n await writeFileSafe(\n join(cwd, \"voxx.json\"),\n render(await readTemplate(\"shared/voxx.json.tpl\"), {\n SITE_TITLE: siteTitle,\n SITE_DESCRIPTION: PRESET_DEFAULTS[preset].description,\n SITE_URL: \"https://example.com\",\n TYPE: preset,\n CONTENT_DIR: contentDir,\n BASE_PATH: basePath,\n }),\n force,\n ),\n ]);\n }\n\n const today = new Date().toISOString().slice(0, 10);\n const samples: Array<[string, string, Record<string, string>?]> =\n preset === \"docs\"\n ? [\n [\"docs/index.md.tpl\", \"index.md\"],\n [\n \"docs/getting-started-index.md.tpl\",\n join(\"01-getting-started\", \"index.md\"),\n ],\n [\n \"docs/installation.md.tpl\",\n join(\"01-getting-started\", \"01-installation.md\"),\n ],\n ]\n : preset === \"changelog\"\n ? [[\"changelog/release.md.tpl\", \"0.1.0.md\", { DATE: today }]]\n : [[\"blog/hello-world.md.tpl\", \"hello-world.md\", { DATE: today }]];\n for (const [tpl, rel, vars] of samples) {\n results.push([\n join(contentDir, rel),\n await writeFileSafe(\n join(cwd, contentDir, rel),\n render(await readTemplate(tpl), vars ?? {}),\n force,\n ),\n ]);\n }\n\n let wroteGlobals = false;\n let cache: CacheComponentsResult | null = null;\n if (hasNext && appDir) {\n const blogDir = join(cwd, appDir, baseSegment);\n const voxxDir = join(blogDir, \"_voxx\");\n const hasTokens = await detectTokens(cwd);\n wroteGlobals = !hasTokens;\n const globalsImport = hasTokens ? \"\" : 'import \"./_voxx/voxx-globals.css\";';\n\n const isolated =\n preset === \"docs\" &&\n !add &&\n createdAppDir !== null &&\n baseSegment !== \"\" &&\n (await isolateCreatedApp(cwd, appDir));\n if (isolated) {\n results.push([\n `${join(appDir, \"(site)\")}/ (app layout moved — docs has its own root layout)`,\n \"written\",\n ]);\n }\n const dataFromAppRoot = baseSegment\n ? `./${baseSegment}/_voxx/data`\n : \"./_voxx/data\";\n const dataFromRouteDir = baseSegment\n ? `../${baseSegment}/_voxx/data`\n : \"../_voxx/data\";\n\n results.push([\n relative(cwd, join(voxxDir, \"voxx.css\")),\n await copyAsset(\"theme/voxx.css\", join(voxxDir, \"voxx.css\"), force),\n ]);\n if (wroteGlobals) {\n results.push([\n relative(cwd, join(voxxDir, \"voxx-globals.css\")),\n await copyAsset(\n \"theme/demo-globals.css\",\n join(voxxDir, \"voxx-globals.css\"),\n force,\n ),\n ]);\n }\n\n const templated: Array<\n [\n tpl: string,\n target: string,\n vars?: Record<string, string>,\n siteWide?: boolean,\n ]\n > = [\n [\n preset === \"docs\"\n ? isolated\n ? \"docs/layout-root.tsx.tpl\"\n : \"docs/layout.tsx.tpl\"\n : `${preset}/layout.tsx.tpl`,\n join(blogDir, \"layout.tsx\"),\n {\n GLOBALS_IMPORT:\n isolated && hasTokens ? 'import \"../globals.css\";' : globalsImport,\n BASE_PATH: basePath,\n RSS_PATH: basePath === \"/\" ? \"/rss.xml\" : `${basePath}/rss.xml`,\n },\n ],\n [\n \"shared/data.ts.tpl\",\n join(voxxDir, \"data.ts\"),\n { COLLECTION_ARG: `{ collection: ${JSON.stringify(collectionName)} }` },\n ],\n [\"shared/content-version.ts.tpl\", join(voxxDir, \"content-version.ts\")],\n [\n \"shared/instrumentation.ts.tpl\",\n join(dirname(join(cwd, appDir)), \"instrumentation.ts\"),\n undefined,\n true,\n ],\n ];\n\n if (preset !== \"changelog\") {\n templated.push(\n [\"shared/on-this-page.tsx.tpl\", join(voxxDir, \"on-this-page.tsx\")],\n [\"shared/metadata.ts.tpl\", join(voxxDir, \"metadata.ts\")],\n [\n \"shared/sitemap.ts.tpl\",\n join(cwd, appDir, \"sitemap.ts\"),\n { DATA_IMPORT: dataFromAppRoot },\n true,\n ],\n [\n \"shared/robots.ts.tpl\",\n join(cwd, appDir, \"robots.ts\"),\n { DATA_IMPORT: dataFromAppRoot },\n true,\n ],\n );\n }\n templated.push(\n [\n \"shared/llms-route.ts.tpl\",\n join(cwd, appDir, \"llms.txt\", \"route.ts\"),\n { DATA_IMPORT: dataFromRouteDir },\n true,\n ],\n [\n \"shared/llms-full-route.ts.tpl\",\n join(cwd, appDir, \"llms-full.txt\", \"route.ts\"),\n { DATA_IMPORT: dataFromRouteDir },\n true,\n ],\n );\n if (preset !== \"docs\") {\n templated.push([\n \"shared/rss-route.ts.tpl\",\n join(blogDir, \"rss.xml\", \"route.ts\"),\n { DATA_IMPORT: \"../_voxx/data\" },\n ]);\n }\n\n if (preset === \"docs\") {\n templated.push(\n [\"docs/page.tsx.tpl\", join(blogDir, \"[[...slug]]\", \"page.tsx\")],\n [\"docs/doc-page.tsx.tpl\", join(voxxDir, \"doc-page.tsx\")],\n [\"docs/sidebar-nav.tsx.tpl\", join(voxxDir, \"sidebar-nav.tsx\")],\n [\"docs/mobile-nav.tsx.tpl\", join(voxxDir, \"mobile-nav.tsx\")],\n [\"shared/theme-toggle.tsx.tpl\", join(voxxDir, \"theme-toggle.tsx\")],\n );\n } else if (preset === \"changelog\") {\n templated.push(\n [\"changelog/page.tsx.tpl\", join(blogDir, \"page.tsx\")],\n [\"changelog/release-list.tsx.tpl\", join(voxxDir, \"release-list.tsx\")],\n [\"shared/theme-toggle.tsx.tpl\", join(voxxDir, \"theme-toggle.tsx\")],\n );\n } else {\n templated.push(\n [\"blog/page.tsx.tpl\", join(blogDir, \"page.tsx\")],\n [\"blog/slug-page.tsx.tpl\", join(blogDir, \"[slug]\", \"page.tsx\")],\n [\"blog/post-page.tsx.tpl\", join(voxxDir, \"post-page.tsx\")],\n [\"blog/post-list.tsx.tpl\", join(voxxDir, \"post-list.tsx\")],\n [\"shared/theme-toggle.tsx.tpl\", join(voxxDir, \"theme-toggle.tsx\")],\n );\n }\n\n for (const [tpl, target, vars, siteWide] of templated) {\n const content = render(await readTemplate(tpl), vars ?? {});\n results.push([\n relative(cwd, target),\n await writeFileSafe(target, content, force),\n siteWide,\n ]);\n }\n\n cache = await enableCacheComponents(cwd, pkg);\n if (cache.kind === \"enabled\" || cache.kind === \"created\") {\n results.push([`${cache.file} (cacheComponents: true)`, \"written\"]);\n }\n }\n\n log.info(\"\");\n log.info(c.bold(add ? \"voxx init --add\" : \"voxx init\"));\n for (const [label, status, siteWide] of results) {\n const mark = status === \"written\" ? c.green(\"+\") : c.dim(\"•\");\n const note =\n status === \"skipped\"\n ? add && siteWide\n ? c.dim(\" (site-wide, already present)\")\n : c.dim(\" (exists, skipped)\")\n : \"\";\n const prefix = createdAppDir ? `${relative(process.cwd(), cwd)}/` : \"\";\n log.info(` ${mark} ${prefix}${label}${note}`);\n }\n\n log.info(\"\");\n log.info(c.bold(\"Next steps:\"));\n if (add) {\n log.info(\n ` 1. Write content in ${c.cyan(`${contentDir}/`)} (try ${c.cyan(`voxx new \"Title\" --collection ${collectionName}`)}).`,\n );\n if (hasNext && appDir) {\n log.info(` 2. Run your dev server and open ${c.cyan(basePath)}.`);\n } else if (hasNext) {\n log.warn(\n \"Next.js found but no app/ directory — pass --app <dir> to scaffold routes.\",\n );\n } else {\n log.info(\n ` 2. Run ${c.cyan(\"voxx build\")} to render static HTML to ${c.cyan(\"./dist\")}.`,\n );\n }\n log.info(\n ` ${c.dim('(Feature defaults like rss/toc follow the first collection\\'s type — review \"features\" in voxx.json.)')}`,\n );\n log.info(\"\");\n return;\n }\n if (staticChoice) {\n const writeHint =\n preset === \"docs\"\n ? `Write pages in ${c.cyan(`${contentDir}/`)} — folders become sections.`\n : preset === \"changelog\"\n ? `Add releases in ${c.cyan(`${contentDir}/`)} (try ${c.cyan('voxx new \"0.2.0\"')}).`\n : `Write posts in ${c.cyan(`${contentDir}/`)} (try ${c.cyan('voxx new \"My post\"')}).`;\n log.info(` 1. ${writeHint}`);\n log.info(` 2. Set ${c.cyan(\"site.url\")} in ${c.cyan(\"voxx.json\")}.`);\n log.info(\n ` 3. Run ${c.cyan(\"voxx build\")} to render static HTML to ${c.cyan(\"./dist\")}.`,\n );\n } else if (!hasNext) {\n log.warn(\"No Next.js detected — wrote voxx.json + sample content only.\");\n log.info(` Install the engine: ${c.cyan(\"npm i @prudentbird/voxx-core\")}`);\n log.info(` Or build static HTML: ${c.cyan(\"npx voxx build\")}`);\n } else if (!appDir) {\n log.warn(\n \"Next.js found but no app/ directory — pass --app <dir> to scaffold routes.\",\n );\n } else {\n let step = 1;\n if (createdAppDir) {\n log.info(\n ` ${step++}. ${c.cyan(`cd ${relative(process.cwd(), createdAppDir)}`)}`,\n );\n }\n log.info(` ${step++}. Install the engine: ${c.cyan(\"npm i @prudentbird/voxx-core\")}`);\n if (cache?.kind === \"manual\") {\n log.info(\n ` ${step++}. Enable Cache Components — add ${c.cyan(\"cacheComponents: true\")} to next.config.`,\n );\n } else if (cache?.kind === \"unsupported\") {\n log.info(\n ` ${step++}. Upgrade to Next 16+ and add ${c.cyan(\"cacheComponents: true\")} to next.config.`,\n );\n }\n log.info(\n ` ${step++}. Set ${c.cyan(\"site.url\")} in ${c.cyan(\"voxx.json\")}.`,\n );\n log.info(` ${step}. Run your dev server and open ${c.cyan(basePath)}.`);\n if (cache?.kind === \"already\") {\n log.info(\n ` ${c.dim(`(Cache Components already enabled in ${cache.file}.)`)}`,\n );\n }\n if (wroteGlobals) {\n log.info(\n ` ${c.dim(\"(No design tokens found — added voxx-globals.css so it looks good out of the box.)\")}`,\n );\n }\n if (preset === \"docs\" && !createdAppDir && appDir) {\n log.info(\n ` ${c.dim(`(Heads up: your root layout wraps ${basePath} — its navbar/footer will show there too. To isolate the docs, see https://voxx.prudentbird.com/docs/reference/layouts.)`)}`,\n );\n }\n }\n log.info(\"\");\n}\n","import { copyFile, mkdir, readdir, writeFile } from \"node:fs/promises\";\nimport type { Dirent } from \"node:fs\";\nimport { dirname, join, relative, sep } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport {\n buildNavTree,\n buildSeo,\n escapeXml as esc,\n formatDate,\n getPosts,\n humanize,\n loadConfig,\n renderLlmsFull,\n renderLlmsTxtSections,\n renderRobotsTxt,\n renderRss,\n renderSitemap,\n rssPath,\n sectionHeading,\n serializeJsonLd,\n type CollectionConfig,\n type NavNode,\n type Post,\n type SeoData,\n type VoxxConfig,\n} from \"@prudentbird/voxx-core\";\nimport { c, exists, log, resolveCoreAsset } from \"../util\";\n\nfunction stripLead(path: string): string {\n return path.replace(/^\\/+/, \"\");\n}\n\nfunction headTags(seo: SeoData, config: VoxxConfig): string {\n const tags: string[] = [\n `<meta name=\"description\" content=\"${esc(seo.description)}\">`,\n `<link rel=\"canonical\" href=\"${esc(seo.canonical)}\">`,\n ];\n const og = seo.openGraph;\n if (og) {\n tags.push(\n `<meta property=\"og:type\" content=\"article\">`,\n `<meta property=\"og:title\" content=\"${esc(og.title)}\">`,\n `<meta property=\"og:description\" content=\"${esc(og.description)}\">`,\n `<meta property=\"og:url\" content=\"${esc(og.url)}\">`,\n `<meta property=\"og:site_name\" content=\"${esc(og.siteName)}\">`,\n ...og.images.map(\n (src) => `<meta property=\"og:image\" content=\"${esc(src)}\">`,\n ),\n );\n }\n if (seo.twitter) {\n tags.push(\n `<meta name=\"twitter:card\" content=\"summary_large_image\">`,\n `<meta name=\"twitter:title\" content=\"${esc(seo.twitter.title)}\">`,\n `<meta name=\"twitter:description\" content=\"${esc(seo.twitter.description)}\">`,\n );\n }\n if (config.seo.jsonLd && seo.jsonLd) {\n tags.push(\n `<script type=\"application/ld+json\">${serializeJsonLd(seo.jsonLd)}</script>`,\n );\n }\n return tags.join(\"\\n \");\n}\n\nfunction shell(opts: {\n title: string;\n lang: string;\n head: string;\n body: string;\n}): string {\n return `<!doctype html>\n<html lang=\"${esc(opts.lang)}\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>${esc(opts.title)}</title>\n <link rel=\"stylesheet\" href=\"/_voxx/voxx-globals.css\">\n <link rel=\"stylesheet\" href=\"/_voxx/voxx.css\">\n ${opts.head}\n </head>\n <body>\n${opts.body}\n </body>\n</html>\n`;\n}\n\nfunction siteHeader(config: VoxxConfig): string {\n const base = config.content.basePath || \"/\";\n const rssIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"><path d=\"M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/><circle cx=\"5\" cy=\"19\" r=\"1\" fill=\"currentColor\"/></svg>`;\n const rss = config.features.rss\n ? `<div class=\"voxx-header__actions\"><a class=\"voxx-icon-button\" href=\"${esc(rssPath(config))}\" aria-label=\"RSS feed\">${rssIcon}</a></div>`\n : \"\";\n return ` <header class=\"voxx voxx-header\">\n <a class=\"voxx-header__title\" href=\"${esc(base)}\">${esc(config.site.title)}</a>\n ${rss}\n </header>`;\n}\n\nfunction metaLine(post: Post, config: VoxxConfig): string {\n const rt = config.features.readingTime\n ? ` · ${post.readingTimeMinutes} min read`\n : \"\";\n return `<time datetime=\"${esc(post.date)}\">${esc(formatDate(post.date, config.site.locale))}</time>${esc(rt)}`;\n}\n\nfunction tocAside(post: Post): string {\n if (post.toc.length === 0) return \"\";\n const items = post.toc\n .map(\n (t) =>\n ` <li class=\"voxx-toc__item\" data-depth=\"${t.depth}\"><a href=\"#${esc(t.id)}\">${esc(t.text)}</a></li>`,\n )\n .join(\"\\n\");\n return ` <aside class=\"voxx-aside\"><div class=\"voxx-aside__inner\">\n <nav class=\"voxx-toc\" aria-label=\"On this page\">\n <p class=\"voxx-toc__title\"><svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><path d=\"M2.5 4h7M2.5 8h11M2.5 12h7\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/></svg>On this page</p>\n <ul class=\"voxx-toc__list\">\n${items}\n </ul>\n </nav>\n </div></aside>`;\n}\n\nfunction indexBody(posts: Post[], config: VoxxConfig): string {\n const cards =\n posts.length === 0\n ? `<p class=\"voxx-empty\">No posts yet.</p>`\n : `<ul class=\"voxx-postlist\">\n${posts\n .map((post) => {\n const tags =\n config.features.tags && post.tags.length\n ? `<ul class=\"voxx-tags\">${post.tags.map((t) => `<li class=\"voxx-tag\">${esc(t)}</li>`).join(\"\")}</ul>`\n : \"\";\n const excerpt = post.excerpt\n ? `<p class=\"voxx-postcard__excerpt\">${esc(post.excerpt)}</p>`\n : \"\";\n return ` <li class=\"voxx-postcard\"><a class=\"voxx-postcard__link\" href=\"${esc(post.url)}\">\n <h2 class=\"voxx-postcard__title\">${esc(post.title)}</h2>\n <p class=\"voxx-postcard__meta\">${metaLine(post, config)}</p>\n ${excerpt}\n ${tags}\n </a></li>`;\n })\n .join(\"\\n\")}\n </ul>`;\n\n return ` <main class=\"voxx voxx-index\">\n <header class=\"voxx-index__header\">\n <h1>${esc(config.site.title)}</h1>\n ${config.site.description ? `<p class=\"voxx-index__desc\">${esc(config.site.description)}</p>` : \"\"}\n </header>\n ${cards}\n </main>`;\n}\n\nfunction postBody(post: Post, config: VoxxConfig): string {\n const aside = config.features.toc ? tocAside(post) : \"\";\n return ` <main class=\"voxx voxx-layout\">\n <article class=\"voxx-article\">\n <header class=\"voxx-article__header\">\n <h1>${esc(post.title)}</h1>\n <p class=\"voxx-article__meta\">${metaLine(post, config)}</p>\n </header>\n <div class=\"voxx-prose\">${post.html}</div>\n </article>\n${aside}\n </main>`;\n}\n\nfunction navHtml(items: NavNode[], activeUrl: string): string {\n if (items.length === 0) return \"\";\n const lis = items\n .map((item) => {\n const label = item.url\n ? `<a class=\"voxx-nav__link\" href=\"${esc(item.url)}\"${item.url === activeUrl ? ' data-active=\"true\"' : \"\"}>${esc(item.title)}</a>`\n : `<span class=\"voxx-nav__section\">${esc(item.title)}</span>`;\n return `<li>${label}${navHtml(item.children, activeUrl)}</li>`;\n })\n .join(\"\\n\");\n return `<ul class=\"voxx-nav__list\">\\n${lis}\\n</ul>`;\n}\n\nfunction pagerHtml(prev: Post | undefined, next: Post | undefined): string {\n if (!prev && !next) return \"\";\n const link = (post: Post, label: string, cls: string) =>\n `<a class=\"voxx-pager__link${cls}\" href=\"${esc(post.url)}\"><span class=\"voxx-pager__label\">${label}</span><span class=\"voxx-pager__title\">${esc(post.title)}</span></a>`;\n return ` <nav class=\"voxx-pager\">\n ${prev ? link(prev, \"Previous\", \"\") : \"<span></span>\"}\n ${next ? link(next, \"Next\", \" voxx-pager__link--next\") : \"<span></span>\"}\n </nav>`;\n}\n\nfunction docsSidebar(\n nav: NavNode[],\n activeUrl: string,\n config: VoxxConfig,\n): string {\n const base = config.content.basePath || \"/\";\n const menuIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/><path d=\"M9 3v18\"/></svg>`;\n return `<aside class=\"voxx-docs__nav\"><div class=\"voxx-docs__nav-inner\">\n <div class=\"voxx-docs__nav-header\">\n <details class=\"voxx-docs__menu\"><summary aria-label=\"Navigation\">${menuIcon}</summary>\n <div class=\"voxx-docs__menu-panel\"><nav class=\"voxx-nav\">${navHtml(nav, activeUrl)}</nav></div>\n </details>\n <a class=\"voxx-docs__title\" href=\"${esc(base)}\">${esc(config.site.title)}</a>\n </div>\n <nav class=\"voxx-nav\">${navHtml(nav, activeUrl)}</nav>\n </div></aside>`;\n}\n\nfunction docBody(\n post: Post,\n posts: Post[],\n index: number,\n nav: NavNode[],\n config: VoxxConfig,\n): string {\n const prev = index > 0 ? posts[index - 1] : undefined;\n const next = posts[index + 1];\n const aside = config.features.toc ? tocAside(post) : \"\";\n const desc = post.description\n ? `<p class=\"voxx-article__meta\">${esc(post.description)}</p>`\n : \"\";\n\n return ` <div class=\"voxx voxx-docs\">\n ${docsSidebar(nav, post.url, config)}\n <main class=\"voxx-layout\">\n <article class=\"voxx-article\">\n <header class=\"voxx-article__header\">\n <h1>${esc(post.title)}</h1>\n ${desc}\n </header>\n <div class=\"voxx-prose\">${post.html}</div>\n${pagerHtml(prev, next)}\n </article>\n${aside}\n </main>\n </div>`;\n}\n\nfunction docsIndexBody(nav: NavNode[], config: VoxxConfig): string {\n return ` <div class=\"voxx voxx-docs\">\n ${docsSidebar(nav, \"\", config)}\n <main class=\"voxx-layout\">\n <article class=\"voxx-article\">\n <header class=\"voxx-article__header\">\n <h1>${esc(config.site.title)}</h1>\n ${config.site.description ? `<p class=\"voxx-article__meta\">${esc(config.site.description)}</p>` : \"\"}\n </header>\n <div class=\"voxx-prose\">${navHtml(nav, \"\")}</div>\n </article>\n </main>\n </div>`;\n}\n\nfunction changelogBody(posts: Post[], config: VoxxConfig): string {\n const releases =\n posts.length === 0\n ? `<p class=\"voxx-empty\">No releases yet.</p>`\n : `<div class=\"voxx-releases\">\n${posts\n .map(\n (post) => ` <section class=\"voxx-release\" id=\"${esc(post.slug)}\">\n <header class=\"voxx-release__header\">\n <h2 class=\"voxx-release__version\"><a href=\"#${esc(post.slug)}\">${esc(post.version ? `v${post.version}` : post.title)}</a></h2>\n <time datetime=\"${esc(post.date)}\">${esc(formatDate(post.date, config.site.locale))}</time>\n </header>\n <div class=\"voxx-prose\">${post.html}</div>\n </section>`,\n )\n .join(\"\\n\")}\n </div>`;\n\n return ` <main class=\"voxx voxx-index\">\n <header class=\"voxx-index__header\">\n <h1>${esc(config.site.title)}</h1>\n ${config.site.description ? `<p class=\"voxx-index__desc\">${esc(config.site.description)}</p>` : \"\"}\n </header>\n ${releases}\n </main>`;\n}\n\n/**\n * Rewrite root-absolute internal links (`href`/`src` beginning with a single\n * `/`) to paths relative to the page's own location. This keeps navigation and\n * asset links working whether the generated site is served from the domain\n * root, a subpath, or opened directly from the filesystem. Protocol-relative\n * (`//host`) and external URLs are left untouched.\n */\nfunction relativizeLinks(\n html: string,\n fromDir: string,\n outDir: string,\n): string {\n const prefix = relative(fromDir, outDir).split(sep).join(\"/\") || \".\";\n return html.replace(/\\b(href|src)=\"\\/(?!\\/)([^\"]*)\"/g, `$1=\"${prefix}/$2\"`);\n}\n\nasync function writePage(\n path: string,\n html: string,\n outDir: string,\n): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n const out = path.endsWith(\".html\")\n ? relativizeLinks(html, dirname(path), outDir)\n : html;\n await writeFile(path, out);\n}\n\nconst SOURCE_RE = /\\.mdx?$/;\n\nasync function copyContentAssets(\n contentDir: string,\n targetDir: string,\n): Promise<number> {\n let copied = 0;\n let entries: Dirent[];\n try {\n entries = await readdir(contentDir, {\n recursive: true,\n withFileTypes: true,\n });\n } catch {\n return 0;\n }\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n const name = entry.name;\n if (SOURCE_RE.test(name) || name.startsWith(\".\")) continue;\n const rel = relative(contentDir, join(entry.parentPath, name));\n const source = join(contentDir, rel);\n const target = join(targetDir, rel);\n await mkdir(dirname(target), { recursive: true });\n await copyFile(source, target);\n copied++;\n }\n return copied;\n}\n\nasync function buildCollection(\n config: VoxxConfig,\n posts: Post[],\n outDir: string,\n): Promise<void> {\n const type = config.content.type;\n const indexPath = join(\n outDir,\n stripLead(config.content.basePath),\n \"index.html\",\n );\n\n if (type === \"changelog\") {\n await writePage(\n indexPath,\n shell({\n title: config.site.title,\n lang: config.site.locale,\n head: `<meta name=\"description\" content=\"${esc(config.site.description)}\">`,\n body: `${siteHeader(config)}\\n${changelogBody(posts, config)}`,\n }),\n outDir,\n );\n } else if (type === \"docs\") {\n const nav = buildNavTree(posts);\n for (let i = 0; i < posts.length; i++) {\n const post = posts[i]!;\n const seo = buildSeo(post, config);\n await writePage(\n join(outDir, stripLead(post.url), \"index.html\"),\n shell({\n title: `${post.title} — ${config.site.title}`,\n lang: config.site.locale,\n head: headTags(seo, config),\n body: docBody(post, posts, i, nav, config),\n }),\n outDir,\n );\n }\n if (!posts.some((p) => p.path.length === 0)) {\n await writePage(\n indexPath,\n shell({\n title: config.site.title,\n lang: config.site.locale,\n head: `<meta name=\"description\" content=\"${esc(config.site.description)}\">`,\n body: docsIndexBody(nav, config),\n }),\n outDir,\n );\n }\n } else {\n await writePage(\n indexPath,\n shell({\n title: config.site.title,\n lang: config.site.locale,\n head: `<meta name=\"description\" content=\"${esc(config.site.description)}\">`,\n body: `${siteHeader(config)}\\n${indexBody(posts, config)}`,\n }),\n outDir,\n );\n\n for (const post of posts) {\n const seo = buildSeo(post, config);\n await writePage(\n join(outDir, stripLead(post.url), \"index.html\"),\n shell({\n title: `${post.title} — ${config.site.title}`,\n lang: config.site.locale,\n head: headTags(seo, config),\n body: `${siteHeader(config)}\\n${postBody(post, config)}`,\n }),\n outDir,\n );\n }\n }\n}\n\nexport interface BuildSiteOptions {\n cwd: string;\n outDir: string;\n includeDrafts?: boolean | undefined;\n quiet?: boolean;\n}\n\nexport interface BuildSiteResult {\n config: VoxxConfig;\n pageCount: number;\n collectionCount: number;\n indexRel: string;\n}\n\nexport async function buildSite(\n opts: BuildSiteOptions,\n): Promise<BuildSiteResult> {\n const { cwd, outDir } = opts;\n const config = await loadConfig({ cwd });\n const collections = config.collections;\n const multi = collections.length > 1;\n\n await mkdir(join(outDir, \"_voxx\"), { recursive: true });\n await copyFile(\n resolveCoreAsset(\"theme/voxx.css\"),\n join(outDir, \"_voxx\", \"voxx.css\"),\n );\n await copyFile(\n resolveCoreAsset(\"theme/demo-globals.css\"),\n join(outDir, \"_voxx\", \"voxx-globals.css\"),\n );\n\n const allPosts: Post[] = [];\n const sections: Array<{ heading: string; posts: Post[] }> = [];\n let pageCount = 0;\n\n for (const collection of collections) {\n const view: VoxxConfig = { ...config, content: { ...collection } };\n const posts = await getPosts({\n config: view,\n includeDrafts: opts.includeDrafts,\n });\n await buildCollection(view, posts, outDir);\n const assetTarget = join(outDir, stripLead(collection.basePath));\n await copyContentAssets(collection.dir, assetTarget);\n\n if (config.features.rss && isFeedType(collection)) {\n await writePage(\n join(outDir, stripLead(rssPath(view))),\n renderRss(posts, view),\n outDir,\n );\n }\n\n sections.push({\n heading: multi\n ? humanize(collection.name)\n : sectionHeading(collection.type),\n posts,\n });\n allPosts.push(...posts);\n pageCount += posts.length;\n }\n\n if (config.features.sitemap) {\n await writeFile(\n join(outDir, \"sitemap.xml\"),\n renderSitemap(allPosts, config, {\n indexPaths: collections.map((col) => col.basePath),\n }),\n );\n await writeFile(join(outDir, \"robots.txt\"), renderRobotsTxt(config));\n }\n if (config.features.llmsTxt) {\n await writeFile(\n join(outDir, \"llms.txt\"),\n renderLlmsTxtSections(sections, config),\n );\n await writeFile(\n join(outDir, \"llms-full.txt\"),\n renderLlmsFull(allPosts, config),\n );\n }\n\n return {\n config,\n pageCount,\n collectionCount: collections.length,\n indexRel: join(\n relative(cwd, outDir),\n stripLead(collections[0]!.basePath),\n \"index.html\",\n ),\n };\n}\n\nfunction isFeedType(collection: CollectionConfig): boolean {\n return collection.type === \"blog\" || collection.type === \"changelog\";\n}\n\nexport async function build(argv: string[]): Promise<void> {\n const { values } = parseArgs({\n args: argv,\n options: {\n out: { type: \"string\" },\n drafts: { type: \"boolean\" },\n },\n allowPositionals: true,\n });\n\n const cwd = process.cwd();\n if (!(await exists(join(cwd, \"voxx.json\")))) {\n log.error(\"No voxx.json found. Run `voxx init` first.\");\n process.exitCode = 1;\n return;\n }\n\n const outDir = join(cwd, values.out ?? \"dist\");\n const result = await buildSite({\n cwd,\n outDir,\n includeDrafts: values.drafts ? true : undefined,\n });\n\n const { config } = result;\n if (!config.site.url || /example\\.com/.test(config.site.url)) {\n log.warn(\n `site.url is ${config.site.url ? `\"${config.site.url}\"` : \"empty\"} — feeds, sitemap, and SEO tags need the real production URL in voxx.json.`,\n );\n }\n\n const type = config.content.type;\n const noun =\n type === \"changelog\" ? \"release\" : type === \"docs\" ? \"page\" : \"post\";\n const what =\n result.collectionCount > 1\n ? `${result.pageCount} pages across ${result.collectionCount} collections`\n : `${result.pageCount} ${noun}${result.pageCount === 1 ? \"\" : \"s\"}`;\n log.success(`Built ${what} → ${relative(cwd, outDir)}/`);\n log.info(\n ` Open ${c.cyan(result.indexRel)} in a browser, or run ${c.cyan(\"voxx dev\")} to preview with a local server.`,\n );\n}\n","import { watch, type FSWatcher } from \"node:fs\";\nimport { mkdtemp, readFile, rm } from \"node:fs/promises\";\nimport { createServer } from \"node:http\";\nimport { tmpdir } from \"node:os\";\nimport { extname, join, normalize } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { loadConfig } from \"@prudentbird/voxx-core\";\nimport { c, exists, log } from \"../util\";\nimport { buildSite } from \"./build\";\n\nconst MIME: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".xml\": \"application/xml; charset=utf-8\",\n \".txt\": \"text/plain; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".avif\": \"image/avif\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".pdf\": \"application/pdf\",\n};\n\nexport interface DevHandle {\n port: number;\n close: () => Promise<void>;\n}\n\nexport async function serveFile(outDir: string, urlPath: string) {\n const decoded = decodeURIComponent(urlPath.split(\"?\")[0] ?? \"/\");\n const safe = normalize(decoded).replace(/^(\\.\\.[\\\\/])+/, \"\");\n const candidates = safe.endsWith(\"/\")\n ? [join(safe, \"index.html\")]\n : [safe, join(safe, \"index.html\")];\n for (const rel of candidates) {\n const path = join(outDir, rel);\n if (!path.startsWith(outDir)) continue;\n try {\n const body = await readFile(path);\n const type =\n MIME[extname(path).toLowerCase()] ?? \"application/octet-stream\";\n return { status: 200, type, body };\n } catch {}\n }\n return {\n status: 404,\n type: \"text/html; charset=utf-8\",\n body: Buffer.from(\"<h1>404</h1><p>Not found.</p>\"),\n };\n}\n\nexport async function dev(argv: string[]): Promise<DevHandle | undefined> {\n const { values } = parseArgs({\n args: argv,\n options: {\n port: { type: \"string\" },\n drafts: { type: \"boolean\" },\n },\n allowPositionals: true,\n });\n\n const cwd = process.cwd();\n if (!(await exists(join(cwd, \"voxx.json\")))) {\n log.error(\"No voxx.json found. Run `voxx init` first.\");\n process.exitCode = 1;\n return;\n }\n\n const port = Number(values.port ?? 4321);\n if (!Number.isInteger(port) || port <= 0 || port > 65535) {\n log.error(`Invalid port \"${values.port}\".`);\n process.exitCode = 1;\n return;\n }\n\n const includeDrafts = values.drafts ?? true;\n const outDir = await mkdtemp(join(tmpdir(), \"voxx-dev-\"));\n\n let building = Promise.resolve();\n let dirty = false;\n const rebuild = (label: string) => {\n building = building.then(async () => {\n try {\n const started = Date.now();\n const result = await buildSite({ cwd, outDir, includeDrafts });\n log.success(\n `${label} — ${result.pageCount} pages in ${Date.now() - started}ms`,\n );\n } catch (err) {\n log.error(err instanceof Error ? err.message : String(err));\n }\n });\n return building;\n };\n\n await rebuild(\"Built\");\n\n const watchers: FSWatcher[] = [];\n const watchPath = (path: string, recursive: boolean) => {\n try {\n const watcher = watch(path, { recursive }, () => {\n if (dirty) return;\n dirty = true;\n setTimeout(() => {\n dirty = false;\n void rebuild(\"Rebuilt\");\n }, 150);\n });\n watchers.push(watcher);\n } catch {\n log.warn(`Could not watch ${path}.`);\n }\n };\n\n const config = await loadConfig({ cwd });\n watchPath(join(cwd, \"voxx.json\"), false);\n for (const collection of config.collections) {\n if (await exists(collection.dir)) watchPath(collection.dir, true);\n }\n\n const server = createServer((req, res) => {\n building\n .then(() => serveFile(outDir, req.url ?? \"/\"))\n .then(({ status, type, body }) => {\n res.writeHead(status, {\n \"Content-Type\": type,\n \"Cache-Control\": \"no-store\",\n });\n res.end(body);\n })\n .catch((err: unknown) => {\n log.error(err instanceof Error ? err.message : String(err));\n if (!res.headersSent) {\n res.writeHead(500, { \"Content-Type\": \"text/plain\" });\n }\n res.end(\"Internal error\");\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(port, resolve);\n }).catch((err: NodeJS.ErrnoException) => {\n log.error(\n err.code === \"EADDRINUSE\"\n ? `Port ${port} is in use — pass --port <n>.`\n : err.message,\n );\n process.exitCode = 1;\n });\n if (process.exitCode === 1) return;\n\n const base = config.collections[0]!.basePath;\n log.info(\"\");\n log.success(`voxx dev serving ${c.cyan(`http://localhost:${port}${base}`)}`);\n log.info(\n ` Watching content for changes${includeDrafts ? \" (drafts included)\" : \"\"}. Press Ctrl+C to stop.`,\n );\n\n const close = () =>\n new Promise<void>((resolve) => {\n for (const watcher of watchers) watcher.close();\n server.close(() => {\n void rm(outDir, { recursive: true, force: true }).finally(resolve);\n });\n });\n\n const shutdown = () => {\n void close().then(() => process.exit(0));\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n return { port, close };\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { parseArgs } from \"node:util\";\nimport {\n parseVersion,\n resolveCollectionDefaults,\n slugify,\n splitDatePrefix,\n splitOrderPrefix,\n} from \"@prudentbird/voxx-core\";\nimport { exists, isSafeRelPath, log, writeFileSafe, yamlValue } from \"../util\";\n\nconst MD_RE = /\\.md$/;\n\ntype ContentType = \"blog\" | \"docs\" | \"changelog\";\n\ninterface VoxxJson {\n content?: { type?: ContentType; dir?: string };\n collections?: Array<{ name?: string; type?: ContentType; dir?: string }>;\n}\n\nasync function readContentConfig(\n cwd: string,\n collectionName?: string,\n): Promise<{ type: ContentType; dir: string } | undefined> {\n const cfgPath = join(cwd, \"voxx.json\");\n if (!(await exists(cfgPath))) return { type: \"blog\", dir: \"content\" };\n const cfg = JSON.parse(await readFile(cfgPath, \"utf8\")) as VoxxJson;\n const collections = (cfg.collections ?? []).map(resolveCollectionDefaults);\n if (collectionName) {\n const found = collections.find((c) => c.name === collectionName);\n if (!found) {\n log.error(\n `Unknown collection \"${collectionName}\" — defined: ${collections.map((c) => c.name).join(\", \")}`,\n );\n return undefined;\n }\n return found;\n }\n const first = collections[0] ?? {\n type: cfg.content?.type ?? \"blog\",\n dir: cfg.content?.dir ?? \"content\",\n };\n return { type: first.type, dir: first.dir };\n}\n\nasync function existingSlugs(dir: string): Promise<Set<string>> {\n const slugs = new Set<string>();\n try {\n for (const entry of await readdir(dir)) {\n if (!MD_RE.test(entry)) continue;\n const { rest } = splitDatePrefix(entry.replace(MD_RE, \"\"));\n slugs.add(slugify(splitOrderPrefix(rest).rest));\n }\n } catch {}\n return slugs;\n}\n\nfunction suggestSlug(base: string, taken: Set<string>): string {\n let slug = base;\n for (let n = 2; taken.has(slug); n++) slug = `${base}-${n}`;\n return slug;\n}\n\nasync function resolveSlug(base: string, taken: Set<string>): Promise<string> {\n if (!taken.has(base)) return base;\n\n let suggestion = suggestSlug(base, taken);\n if (!process.stdin.isTTY) {\n log.warn(`Slug \"${base}\" is taken — using \"${suggestion}\".`);\n return suggestion;\n }\n\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n let takenName = base;\n for (;;) {\n const answer = (\n await rl.question(\n `Slug \"${takenName}\" is taken. Enter a new slug, or press Enter for \"${suggestion}\": `,\n )\n ).trim();\n if (!answer) return suggestion;\n\n const candidate = slugify(answer);\n if (!candidate) {\n log.warn(\"Please enter a valid slug.\");\n continue;\n }\n if (!taken.has(candidate)) return candidate;\n\n log.warn(`\"${candidate}\" is also taken.`);\n takenName = candidate;\n suggestion = suggestSlug(candidate, taken);\n }\n } finally {\n rl.close();\n }\n}\n\nexport async function newPost(argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n dir: { type: \"string\" },\n date: { type: \"string\" },\n slug: { type: \"string\" },\n flat: { type: \"boolean\" },\n section: { type: \"string\" },\n order: { type: \"string\" },\n collection: { type: \"string\" },\n index: { type: \"boolean\" },\n },\n allowPositionals: true,\n });\n\n const title = positionals.join(\" \").trim();\n if (!title) {\n log.error('Usage: voxx new \"My Post Title\"');\n process.exitCode = 1;\n return;\n }\n\n const cwd = process.cwd();\n const detected = await readContentConfig(cwd, values.collection);\n if (!detected) {\n process.exitCode = 1;\n return;\n }\n const contentDir = values.dir ?? detected.dir;\n if (!isSafeRelPath(contentDir)) {\n log.error(\n `Invalid --dir \"${contentDir}\" — must stay within the project (no \"..\").`,\n );\n process.exitCode = 1;\n return;\n }\n if (values.index && detected.type !== \"docs\") {\n log.error(\"--index only applies to docs content.\");\n process.exitCode = 1;\n return;\n }\n const date = values.date ?? new Date().toISOString().slice(0, 10);\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n log.error(`Invalid --date \"${values.date}\" — expected YYYY-MM-DD.`);\n process.exitCode = 1;\n return;\n }\n\n if (detected.type === \"changelog\") {\n const version = parseVersion(title) ?? title;\n if (\n !isSafeRelPath(`${version}.md`) ||\n version.includes(\"/\") ||\n version.includes(\"\\\\\")\n ) {\n log.error(\n `Invalid changelog name \"${title}\" — use a version like \"1.2.0\".`,\n );\n process.exitCode = 1;\n return;\n }\n const target = join(cwd, contentDir, `${version}.md`);\n const body = [\n \"---\",\n `title: ${yamlValue(`v${version}`)}`,\n `version: ${yamlValue(version)}`,\n `date: ${date}`,\n \"---\",\n \"\",\n \"### Added\",\n \"\",\n \"- \",\n \"\",\n ].join(\"\\n\");\n const status = await writeFileSafe(target, body, false);\n if (status === \"skipped\") {\n log.warn(`${relative(cwd, target)} already exists — left untouched.`);\n } else {\n log.success(`Created ${relative(cwd, target)}`);\n }\n return;\n }\n\n const baseSlug = slugify(values.slug ?? title);\n if (!baseSlug) {\n log.error(\"Could not derive a slug — pass --slug.\");\n process.exitCode = 1;\n return;\n }\n\n if (detected.type === \"docs\") {\n if (values.section && !isSafeRelPath(values.section)) {\n log.error(\n `Invalid --section \"${values.section}\" — must stay within the content directory (no \"..\").`,\n );\n process.exitCode = 1;\n return;\n }\n const section = (values.section ?? \"\").split(\"/\").filter(Boolean).join(\"/\");\n const targetDir = section\n ? join(cwd, contentDir, section)\n : join(cwd, contentDir);\n if (values.index) {\n const target = join(targetDir, \"index.md\");\n const body = [\n \"---\",\n `title: ${yamlValue(title)}`,\n \"description: \",\n \"---\",\n \"\",\n \"Write your section landing page here.\",\n \"\",\n ].join(\"\\n\");\n const status = await writeFileSafe(target, body, false);\n if (status === \"skipped\") {\n log.warn(`${relative(cwd, target)} already exists — left untouched.`);\n } else {\n log.success(`Created ${relative(cwd, target)}`);\n }\n return;\n }\n const taken = await existingSlugs(targetDir);\n const slug = await resolveSlug(baseSlug, taken);\n const order = values.order ? Number(values.order) : undefined;\n const fileName =\n order !== undefined && Number.isFinite(order)\n ? `${String(order).padStart(2, \"0\")}-${slug}.md`\n : `${slug}.md`;\n const target = join(targetDir, fileName);\n const body = [\n \"---\",\n `title: ${yamlValue(title)}`,\n \"description: \",\n \"---\",\n \"\",\n \"Write your page here.\",\n \"\",\n ].join(\"\\n\");\n const status = await writeFileSafe(target, body, false);\n if (status === \"skipped\") {\n log.warn(`${relative(cwd, target)} already exists — left untouched.`);\n } else {\n log.success(`Created ${relative(cwd, target)}`);\n }\n return;\n }\n\n const taken = await existingSlugs(join(cwd, contentDir));\n const slug = await resolveSlug(baseSlug, taken);\n\n const fileName = values.flat ? `${slug}.md` : `${date}-${slug}.md`;\n const target = join(cwd, contentDir, fileName);\n\n const body = [\n \"---\",\n `title: ${yamlValue(title)}`,\n \"description: \",\n `date: ${date}`,\n `slug: ${slug}`,\n \"tags: []\",\n \"---\",\n \"\",\n \"Write your post here.\",\n \"\",\n ].join(\"\\n\");\n\n const status = await writeFileSafe(target, body, false);\n if (status === \"skipped\") {\n log.warn(`${relative(cwd, target)} already exists — left untouched.`);\n } else {\n log.success(`Created ${relative(cwd, target)}`);\n }\n}\n","#!/usr/bin/env node\nimport { c, log } from \"./util\";\nimport { init } from \"./commands/init\";\nimport { build } from \"./commands/build\";\nimport { dev } from \"./commands/dev\";\nimport { newPost } from \"./commands/new\";\n\nconst HELP = `${c.bold(\"voxx\")} — a zero-friction, file-based CMS for blogs and docs\n\n${c.bold(\"Usage:\")}\n voxx init [blog|docs|changelog] [--dir <content>] [--base <path>] [--app <dir>] [--force]\n voxx init --add [blog|docs|changelog] [--name <name>] [--dir <dir>] [--base <path>] [--app <dir>]\n voxx new \"Title\" [--collection <name>] [--slug <slug>] [--dir <content>] [--date <YYYY-MM-DD>] [--flat] [--section <path>] [--order <n>] [--index]\n voxx build [--out <dir>] [--drafts]\n voxx dev [--port <n>] [--drafts]\n\n${c.bold(\"Examples:\")}\n voxx init Scaffold a blog into your Next.js app\n voxx init docs Scaffold a docs site instead\n voxx init changelog Scaffold a release-notes page\n voxx init --add docs Add a docs collection to an existing site\n voxx new \"Hello world\" Create a new markdown post (or doc page, or release)\n voxx new \"Guides\" --section guides --index Create a docs section's index.md landing page\n voxx build Render a static HTML site to ./dist\n voxx dev Preview the static site locally, rebuilding on change\n`;\n\nasync function main(): Promise<void> {\n const [cmd, ...rest] = process.argv.slice(2);\n switch (cmd) {\n case \"init\":\n await init(rest);\n break;\n case \"new\":\n await newPost(rest);\n break;\n case \"build\":\n await build(rest);\n break;\n case \"dev\":\n await dev(rest);\n break;\n case undefined:\n case \"-h\":\n case \"--help\":\n log.info(HELP);\n break;\n default:\n log.error(`Unknown command: ${cmd}`);\n log.info(HELP);\n process.exitCode = 1;\n }\n}\n\nmain().catch((err) => {\n log.error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["esc"],"sources":["../src/util.ts","../src/commands/init.ts","../src/commands/build.ts","../src/commands/dev.ts","../src/commands/new.ts","../src/index.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { access, mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst require = createRequire(import.meta.url);\nconst TEMPLATES_DIR = fileURLToPath(new URL(\"../templates\", import.meta.url));\n\nconst useColor = process.stdout.isTTY && !process.env[\"NO_COLOR\"];\nconst wrap = (code: string) => (s: string) =>\n useColor ? `[${code}m${s}[0m` : s;\n\n/** ANSI color helpers that degrade gracefully in non-TTY environments. */\nexport const c = {\n bold: wrap(\"1\"),\n dim: wrap(\"2\"),\n red: wrap(\"31\"),\n green: wrap(\"32\"),\n yellow: wrap(\"33\"),\n cyan: wrap(\"36\"),\n};\n\n/** Prefixed console helpers used throughout the CLI commands. */\nexport const log = {\n info: (msg: string) => console.log(msg),\n success: (msg: string) => console.log(`${c.green(\"✓\")} ${msg}`),\n warn: (msg: string) => console.log(`${c.yellow(\"!\")} ${msg}`),\n error: (msg: string) => console.error(`${c.red(\"✗\")} ${msg}`),\n};\n\n/**\n * Returns `true` if the path exists and is accessible, `false` otherwise.\n */\nexport async function exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Reads a scaffold template file by name from the bundled `templates/` directory.\n *\n * @param name - Template filename, e.g. `\"shared/data.ts.tpl\"`.\n */\nexport async function readTemplate(name: string): Promise<string> {\n return readFile(join(TEMPLATES_DIR, name), \"utf8\");\n}\n\n/**\n * Replaces `{{KEY}}` placeholders in a template string.\n *\n * @param tpl - Template string containing `{{VARIABLE}}` tokens.\n * @param vars - Map of token names to replacement values.\n */\nexport function render(tpl: string, vars: Record<string, string> = {}): string {\n return tpl.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => vars[key] ?? \"\");\n}\n\n/** Result of a `writeFileSafe` call. */\nexport type WriteStatus = \"written\" | \"skipped\";\n\n/**\n * Writes `content` to `path`, creating parent directories as needed.\n * Skips the write if the file already exists and `force` is `false`.\n *\n * @param path - Destination file path.\n * @param content - File content to write.\n * @param force - Overwrite existing files when `true`. Defaults to `false`.\n * @returns `\"written\"` if the file was created/replaced, `\"skipped\"` if it already existed.\n */\nexport async function writeFileSafe(\n path: string,\n content: string,\n force = false,\n): Promise<WriteStatus> {\n await mkdir(dirname(path), { recursive: true });\n if (!force && (await exists(path))) return \"skipped\";\n await writeFile(path, content);\n return \"written\";\n}\n\n/**\n * Resolves the path to a sub-asset of the installed `@prudentbird/voxx-core` package.\n *\n * @param subpath - Package-relative path, e.g. `\"theme/voxx.css\"`.\n */\nexport function resolveCoreAsset(subpath: string): string {\n return require.resolve(`@prudentbird/voxx-core/${subpath}`);\n}\n\n/**\n * Converts a package name or slug to Title Case.\n *\n * Strips any npm scope prefix (`@scope/`) before converting.\n */\nexport function titleCase(name: string): string {\n return name\n .replace(/^@[^/]+\\//, \"\")\n .replace(/[-_]+/g, \" \")\n .replace(/\\b\\w/g, (m) => m.toUpperCase())\n .trim();\n}\n\n/**\n * Returns `true` if the path is a safe relative path that stays within the\n * project root (no absolute paths, no `..` traversal, no null bytes).\n */\nexport function isSafeRelPath(p: string): boolean {\n if (p === \"\") return true;\n if (p.includes(\"\\0\")) return false;\n if (p.startsWith(\"/\") || /^[A-Za-z]:[\\\\/]/.test(p)) return false;\n return p.split(/[\\\\/]/).every((seg) => seg !== \"..\");\n}\n\n/**\n * Normalizes a URL base path to always have a leading slash and no trailing slash.\n *\n * @param base - Raw base path, e.g. `\"blog/\"` or `\"/blog\"`.\n * @returns Normalized path, e.g. `\"/blog\"`.\n */\nexport function normalizeBase(base: string): string {\n const withLead = base.startsWith(\"/\") ? base : `/${base}`;\n return withLead.length > 1 ? withLead.replace(/\\/+$/, \"\") : withLead;\n}\n\nconst YAML_PLAIN_RE = /^[A-Za-z0-9](?:[A-Za-z0-9 ._/()-]*[A-Za-z0-9._/()-])?$/;\n\n/**\n * Returns a YAML-safe representation of `value`.\n *\n * Plain strings that match the safe character set are returned as-is;\n * everything else is JSON-quoted.\n */\nexport function yamlValue(value: string): string {\n return YAML_PLAIN_RE.test(value) ? value : JSON.stringify(value);\n}\n","import { spawn } from \"node:child_process\";\nimport { copyFile, mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { parseArgs } from \"node:util\";\nimport {\n DEFAULT_CONFIG,\n resolveCollectionDefaults,\n type CollectionInput,\n} from \"@prudentbird/voxx-core\";\nimport {\n c,\n exists,\n isSafeRelPath,\n log,\n normalizeBase,\n readTemplate,\n render,\n resolveCoreAsset,\n titleCase,\n writeFileSafe,\n type WriteStatus,\n} from \"../util\";\n\nconst APP_DIR_CANDIDATES = [\"app\", \"src/app\"];\nconst GLOBALS_CANDIDATES = [\n \"app/globals.css\",\n \"src/app/globals.css\",\n \"styles/globals.css\",\n \"src/styles/globals.css\",\n \"app/global.css\",\n];\n\nconst PRESETS = [\"blog\", \"docs\", \"changelog\"] as const;\ntype Preset = (typeof PRESETS)[number];\n\nconst PRESET_DEFAULTS: Record<Preset, { title: string; description: string }> =\n {\n blog: { title: \"My Blog\", description: \"A blog built with Voxx.\" },\n docs: { title: \"My Docs\", description: \"Documentation built with Voxx.\" },\n changelog: {\n title: \"Changelog\",\n description: \"Release notes built with Voxx.\",\n },\n };\n\ntype Pkg = {\n name?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n};\n\nasync function readPkg(cwd: string): Promise<Pkg> {\n if (await exists(join(cwd, \"package.json\"))) {\n return JSON.parse(await readFile(join(cwd, \"package.json\"), \"utf8\"));\n }\n return {};\n}\n\nfunction pkgHasNext(pkg: Pkg): boolean {\n return Boolean(pkg.dependencies?.[\"next\"] ?? pkg.devDependencies?.[\"next\"]);\n}\n\nasync function detectAppDir(cwd: string): Promise<string | null> {\n for (const dir of APP_DIR_CANDIDATES) {\n if (await exists(join(cwd, dir))) return dir;\n }\n return null;\n}\n\nasync function detectTokens(cwd: string): Promise<boolean> {\n for (const rel of GLOBALS_CANDIDATES) {\n const path = join(cwd, rel);\n if (await exists(path)) {\n const css = await readFile(path, \"utf8\");\n if (css.includes(\"--background\") || css.includes(\"--foreground\"))\n return true;\n }\n }\n return false;\n}\n\nasync function copyAsset(\n subpath: string,\n target: string,\n force: boolean,\n): Promise<WriteStatus> {\n if (!force && (await exists(target))) return \"skipped\";\n await mkdir(dirname(target), { recursive: true });\n await copyFile(resolveCoreAsset(subpath), target);\n return \"written\";\n}\n\nfunction run(cmd: string, args: string[], cwd: string): Promise<number> {\n return new Promise((resolve, reject) => {\n const child = spawn(cmd, args, { cwd, stdio: \"inherit\" });\n child.on(\"error\", reject);\n child.on(\"close\", (code) => resolve(code ?? 1));\n });\n}\n\nasync function chooseSetup(): Promise<\"static\" | \"next\"> {\n if (!process.stdin.isTTY) return \"static\";\n\n log.warn(\"No Next.js app detected here.\");\n log.info(\n ` ${c.cyan(\"1.\")} Static site — markdown in, HTML/CSS out via ${c.cyan(\"voxx build\")}`,\n );\n log.info(\n ` ${c.cyan(\"2.\")} New Next.js app — runs ${c.cyan(\"create-next-app\")}, then scaffolds`,\n );\n\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n for (;;) {\n const answer = (await rl.question(`Choose [1/2] (default 1): `)).trim();\n if (answer === \"\" || answer === \"1\") return \"static\";\n if (answer === \"2\") return \"next\";\n log.warn(\"Please answer 1 or 2.\");\n }\n } finally {\n rl.close();\n }\n}\n\nasync function createNextApp(cwd: string): Promise<string | null> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n let dir: string;\n try {\n dir =\n (\n await rl.question(\n `Directory for the new app (default ${c.cyan(\"my-app\")}): `,\n )\n ).trim() || \"my-app\";\n } finally {\n rl.close();\n }\n\n log.info(\"\");\n const code = await run(\"npx\", [\"create-next-app@latest\", dir], cwd);\n if (code !== 0) {\n log.error(\"create-next-app failed — nothing scaffolded.\");\n return null;\n }\n return join(cwd, dir);\n}\n\nasync function isolateCreatedApp(\n cwd: string,\n appDir: string,\n): Promise<boolean> {\n const siteDir = join(cwd, appDir, \"(site)\");\n const moved: string[] = [];\n for (const file of [\n \"layout.tsx\",\n \"layout.js\",\n \"page.tsx\",\n \"page.js\",\n \"page.module.css\",\n ]) {\n const from = join(cwd, appDir, file);\n if (!(await exists(from))) continue;\n await mkdir(siteDir, { recursive: true });\n await rename(from, join(siteDir, file));\n moved.push(file);\n }\n if (!moved.some((f) => f.startsWith(\"layout.\"))) return false;\n for (const file of [\"layout.tsx\", \"layout.js\"]) {\n const path = join(siteDir, file);\n if (!(await exists(path))) continue;\n const src = await readFile(path, \"utf8\");\n await writeFile(path, src.replace('\"./globals.css\"', '\"../globals.css\"'));\n }\n return true;\n}\n\nconst NEXT_CONFIG_FILES = [\n \"next.config.ts\",\n \"next.config.mjs\",\n \"next.config.js\",\n \"next.config.cjs\",\n];\n\nfunction nextMajor(pkg: Pkg): number | null {\n const range =\n pkg.dependencies?.[\"next\"] ?? pkg.devDependencies?.[\"next\"] ?? \"\";\n const m = /(\\d+)/.exec(range);\n return m ? Number(m[1]) : null;\n}\n\nconst MINIMAL_NEXT_CONFIG = `import type { NextConfig } from \"next\";\n\nconst nextConfig: NextConfig = {\n cacheComponents: true,\n};\n\nexport default nextConfig;\n`;\n\ntype CacheComponentsResult =\n | { kind: \"enabled\" | \"created\" | \"already\"; file: string }\n | { kind: \"manual\" | \"unsupported\" };\n\nasync function enableCacheComponents(\n cwd: string,\n pkg: Pkg,\n): Promise<CacheComponentsResult> {\n const major = nextMajor(pkg);\n if (major !== null && major < 16) return { kind: \"unsupported\" };\n\n let file: string | null = null;\n for (const name of NEXT_CONFIG_FILES) {\n if (await exists(join(cwd, name))) {\n file = name;\n break;\n }\n }\n\n if (!file) {\n if (major === null) return { kind: \"manual\" };\n await writeFile(join(cwd, \"next.config.ts\"), MINIMAL_NEXT_CONFIG);\n return { kind: \"created\", file: \"next.config.ts\" };\n }\n\n const source = await readFile(join(cwd, file), \"utf8\");\n if (/\\bcacheComponents\\b/.test(source)) return { kind: \"already\", file };\n\n const m =\n /(const\\s+nextConfig\\s*(?::\\s*[\\w.]+)?\\s*=\\s*|export\\s+default\\s+|module\\.exports\\s*=\\s*)\\{/.exec(\n source,\n );\n if (!m) return { kind: \"manual\" };\n\n const at = m.index + m[0].length;\n const rest = source.slice(at);\n const insert = rest.trimStart().startsWith(\"}\")\n ? \"\\n cacheComponents: true,\\n\"\n : \"\\n cacheComponents: true,\";\n await writeFile(join(cwd, file), source.slice(0, at) + insert + rest);\n return { kind: \"enabled\", file };\n}\n\ntype RawConfig = Record<string, unknown>;\n\ntype AddPlan =\n | {\n ok: true;\n out: RawConfig;\n name: string;\n dir: string;\n basePath: string;\n }\n | { ok: false; message: string };\n\nfunction planAdd(\n raw: RawConfig,\n preset: Preset,\n values: { name?: string; dir?: string; base?: string },\n): AddPlan {\n const rawCollections = Array.isArray(raw[\"collections\"])\n ? (raw[\"collections\"] as CollectionInput[])\n : [];\n const rawContent = (raw[\"content\"] ?? undefined) as\n | CollectionInput\n | undefined;\n\n const existing =\n rawCollections.length > 0\n ? rawCollections.map(resolveCollectionDefaults)\n : [\n {\n name: rawContent?.type ?? DEFAULT_CONFIG.content.type,\n type: rawContent?.type ?? DEFAULT_CONFIG.content.type,\n dir: rawContent?.dir ?? DEFAULT_CONFIG.content.dir,\n basePath: rawContent?.basePath ?? DEFAULT_CONFIG.content.basePath,\n drafts: rawContent?.drafts ?? false,\n },\n ];\n const first = existing[0]!;\n\n const name = values.name ?? preset;\n const dir = values.dir ?? `content/${name}`;\n const basePath = normalizeBase(values.base ?? `/${name}`);\n\n if (existing.some((c) => c.name === name)) {\n return {\n ok: false,\n message: `Collection \"${name}\" already exists — defined: ${existing\n .map((c) => c.name)\n .join(\", \")}. Pass --name <other>.`,\n };\n }\n const dupBase = existing.find((c) => c.basePath === basePath);\n if (dupBase) {\n return {\n ok: false,\n message: `Base path \"${basePath}\" is already used by collection \"${dupBase.name}\" — pass --base <path>.`,\n };\n }\n const dupDir = existing.find((c) => c.dir === dir);\n if (dupDir) {\n return {\n ok: false,\n message: `Content dir \"${dir}\" is already used by collection \"${dupDir.name}\" — pass --dir <dir>.`,\n };\n }\n\n const next = { name, type: preset, dir, basePath, drafts: false };\n\n if (rawCollections.length > 0) {\n return {\n ok: true,\n out: { ...raw, collections: [...rawCollections, next] },\n name,\n dir,\n basePath,\n };\n }\n\n const migrated: Record<string, unknown> = {\n name: first.name,\n ...(rawContent ?? {}),\n };\n const reResolved = resolveCollectionDefaults(migrated as CollectionInput);\n if (reResolved.dir !== first.dir) migrated[\"dir\"] = first.dir;\n if (reResolved.basePath !== first.basePath) {\n migrated[\"basePath\"] = first.basePath;\n }\n\n const collections = [migrated, next];\n const out: RawConfig = {};\n let inserted = false;\n for (const [key, value] of Object.entries(raw)) {\n if (key === \"content\" || key === \"collections\") {\n if (!inserted) {\n out[\"collections\"] = collections;\n inserted = true;\n }\n continue;\n }\n out[key] = value;\n }\n if (!inserted) out[\"collections\"] = collections;\n\n return { ok: true, out, name, dir, basePath };\n}\n\nexport async function init(argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n dir: { type: \"string\" },\n base: { type: \"string\" },\n app: { type: \"string\" },\n name: { type: \"string\" },\n add: { type: \"boolean\" },\n force: { type: \"boolean\" },\n },\n allowPositionals: true,\n });\n\n const presetArg = positionals[0] ?? \"blog\";\n if (!(PRESETS as readonly string[]).includes(presetArg)) {\n log.error(\n `Unknown preset \"${presetArg}\" — expected one of: ${PRESETS.join(\", \")}.`,\n );\n process.exitCode = 1;\n return;\n }\n const preset = presetArg as Preset;\n const add = Boolean(values.add);\n const force = Boolean(values.force);\n\n if (add && force) {\n log.error(\n \"--add and --force cannot be combined — --add never overwrites. Delete the collection's files and re-run if you need a clean re-scaffold.\",\n );\n process.exitCode = 1;\n return;\n }\n if (!add && values.name !== undefined) {\n log.error(\"--name only applies with --add.\");\n process.exitCode = 1;\n return;\n }\n\n if (values.dir !== undefined && !isSafeRelPath(values.dir)) {\n log.error(\n `Invalid --dir \"${values.dir}\" — must stay within the project (no \"..\").`,\n );\n process.exitCode = 1;\n return;\n }\n if (values.app !== undefined && !isSafeRelPath(values.app)) {\n log.error(\n `Invalid --app \"${values.app}\" — must stay within the project (no \"..\").`,\n );\n process.exitCode = 1;\n return;\n }\n if (values.base !== undefined && values.base.split(/[\\\\/]/).includes(\"..\")) {\n log.error(`Invalid --base \"${values.base}\" — must not contain \"..\".`);\n process.exitCode = 1;\n return;\n }\n\n let cwd = process.cwd();\n let contentDir = values.dir ?? \"content\";\n let basePath = normalizeBase(values.base ?? `/${preset}`);\n let collectionName: string = preset;\n\n let pkg = await readPkg(cwd);\n let hasNext = pkgHasNext(pkg);\n let createdAppDir: string | null = null;\n let staticChoice = false;\n\n const results: Array<\n [label: string, status: WriteStatus, siteWide?: boolean]\n > = [];\n\n if (add) {\n const cfgPath = join(cwd, \"voxx.json\");\n if (!(await exists(cfgPath))) {\n log.error(\n `--add requires an existing voxx.json — run ${c.cyan(`voxx init ${preset}`)} first.`,\n );\n process.exitCode = 1;\n return;\n }\n let raw: RawConfig;\n try {\n raw = JSON.parse(await readFile(cfgPath, \"utf8\")) as RawConfig;\n } catch {\n log.error(\"voxx.json is not valid JSON — fix it before running --add.\");\n process.exitCode = 1;\n return;\n }\n const plan = planAdd(raw, preset, values);\n if (!plan.ok) {\n log.error(plan.message);\n process.exitCode = 1;\n return;\n }\n collectionName = plan.name;\n contentDir = plan.dir;\n basePath = plan.basePath;\n await writeFile(cfgPath, `${JSON.stringify(plan.out, null, 2)}\\n`);\n results.push([\n `voxx.json (added collection \"${collectionName}\")`,\n \"written\",\n ]);\n } else if (!hasNext) {\n const setup = await chooseSetup();\n if (setup === \"next\") {\n createdAppDir = await createNextApp(cwd);\n if (!createdAppDir) {\n process.exitCode = 1;\n return;\n }\n cwd = createdAppDir;\n pkg = await readPkg(cwd);\n hasNext = pkgHasNext(pkg);\n } else {\n staticChoice = true;\n }\n }\n\n const baseSegment = basePath.slice(1);\n const appDir = values.app ?? (await detectAppDir(cwd));\n const siteTitle = pkg.name\n ? titleCase(pkg.name)\n : PRESET_DEFAULTS[preset].title;\n\n if (!add) {\n results.push([\n \"voxx.json\",\n await writeFileSafe(\n join(cwd, \"voxx.json\"),\n render(await readTemplate(\"shared/voxx.json.tpl\"), {\n SITE_TITLE: siteTitle,\n SITE_DESCRIPTION: PRESET_DEFAULTS[preset].description,\n SITE_URL: \"https://example.com\",\n TYPE: preset,\n CONTENT_DIR: contentDir,\n BASE_PATH: basePath,\n }),\n force,\n ),\n ]);\n }\n\n const today = new Date().toISOString().slice(0, 10);\n const samples: Array<[string, string, Record<string, string>?]> =\n preset === \"docs\"\n ? [\n [\"docs/index.md.tpl\", \"index.md\"],\n [\n \"docs/getting-started-index.md.tpl\",\n join(\"01-getting-started\", \"index.md\"),\n ],\n [\n \"docs/installation.md.tpl\",\n join(\"01-getting-started\", \"01-installation.md\"),\n ],\n ]\n : preset === \"changelog\"\n ? [[\"changelog/release.md.tpl\", \"0.1.0.md\", { DATE: today }]]\n : [[\"blog/hello-world.md.tpl\", \"hello-world.md\", { DATE: today }]];\n for (const [tpl, rel, vars] of samples) {\n results.push([\n join(contentDir, rel),\n await writeFileSafe(\n join(cwd, contentDir, rel),\n render(await readTemplate(tpl), vars ?? {}),\n force,\n ),\n ]);\n }\n\n let wroteGlobals = false;\n let cache: CacheComponentsResult | null = null;\n if (hasNext && appDir) {\n const blogDir = join(cwd, appDir, baseSegment);\n const voxxDir = join(blogDir, \"_voxx\");\n const hasTokens = await detectTokens(cwd);\n wroteGlobals = !hasTokens;\n const globalsImport = hasTokens ? \"\" : 'import \"./_voxx/voxx-globals.css\";';\n\n const isolated =\n preset === \"docs\" &&\n !add &&\n createdAppDir !== null &&\n baseSegment !== \"\" &&\n (await isolateCreatedApp(cwd, appDir));\n if (isolated) {\n results.push([\n `${join(appDir, \"(site)\")}/ (app layout moved — docs has its own root layout)`,\n \"written\",\n ]);\n }\n const dataFromAppRoot = baseSegment\n ? `./${baseSegment}/_voxx/data`\n : \"./_voxx/data\";\n const dataFromRouteDir = baseSegment\n ? `../${baseSegment}/_voxx/data`\n : \"../_voxx/data\";\n\n results.push([\n relative(cwd, join(voxxDir, \"voxx.css\")),\n await copyAsset(\"theme/voxx.css\", join(voxxDir, \"voxx.css\"), force),\n ]);\n if (wroteGlobals) {\n results.push([\n relative(cwd, join(voxxDir, \"voxx-globals.css\")),\n await copyAsset(\n \"theme/demo-globals.css\",\n join(voxxDir, \"voxx-globals.css\"),\n force,\n ),\n ]);\n }\n\n const templated: Array<\n [\n tpl: string,\n target: string,\n vars?: Record<string, string>,\n siteWide?: boolean,\n ]\n > = [\n [\n preset === \"docs\"\n ? isolated\n ? \"docs/layout-root.tsx.tpl\"\n : \"docs/layout.tsx.tpl\"\n : `${preset}/layout.tsx.tpl`,\n join(blogDir, \"layout.tsx\"),\n {\n GLOBALS_IMPORT:\n isolated && hasTokens ? 'import \"../globals.css\";' : globalsImport,\n BASE_PATH: basePath,\n RSS_PATH: basePath === \"/\" ? \"/rss.xml\" : `${basePath}/rss.xml`,\n },\n ],\n [\n \"shared/data.ts.tpl\",\n join(voxxDir, \"data.ts\"),\n { COLLECTION_ARG: `{ collection: ${JSON.stringify(collectionName)} }` },\n ],\n [\"shared/content-version.ts.tpl\", join(voxxDir, \"content-version.ts\")],\n [\n \"shared/instrumentation.ts.tpl\",\n join(dirname(join(cwd, appDir)), \"instrumentation.ts\"),\n undefined,\n true,\n ],\n ];\n\n if (preset !== \"changelog\") {\n templated.push(\n [\"shared/on-this-page.tsx.tpl\", join(voxxDir, \"on-this-page.tsx\")],\n [\"shared/metadata.ts.tpl\", join(voxxDir, \"metadata.ts\")],\n [\n \"shared/sitemap.ts.tpl\",\n join(cwd, appDir, \"sitemap.ts\"),\n { DATA_IMPORT: dataFromAppRoot },\n true,\n ],\n [\n \"shared/robots.ts.tpl\",\n join(cwd, appDir, \"robots.ts\"),\n { DATA_IMPORT: dataFromAppRoot },\n true,\n ],\n );\n }\n templated.push(\n [\n \"shared/llms-route.ts.tpl\",\n join(cwd, appDir, \"llms.txt\", \"route.ts\"),\n { DATA_IMPORT: dataFromRouteDir },\n true,\n ],\n [\n \"shared/llms-full-route.ts.tpl\",\n join(cwd, appDir, \"llms-full.txt\", \"route.ts\"),\n { DATA_IMPORT: dataFromRouteDir },\n true,\n ],\n );\n if (preset !== \"docs\") {\n templated.push([\n \"shared/rss-route.ts.tpl\",\n join(blogDir, \"rss.xml\", \"route.ts\"),\n { DATA_IMPORT: \"../_voxx/data\" },\n ]);\n }\n\n if (preset === \"docs\") {\n templated.push(\n [\"docs/page.tsx.tpl\", join(blogDir, \"[[...slug]]\", \"page.tsx\")],\n [\"docs/doc-page.tsx.tpl\", join(voxxDir, \"doc-page.tsx\")],\n [\"docs/sidebar-nav.tsx.tpl\", join(voxxDir, \"sidebar-nav.tsx\")],\n [\"docs/mobile-nav.tsx.tpl\", join(voxxDir, \"mobile-nav.tsx\")],\n [\"shared/theme-toggle.tsx.tpl\", join(voxxDir, \"theme-toggle.tsx\")],\n );\n } else if (preset === \"changelog\") {\n templated.push(\n [\"changelog/page.tsx.tpl\", join(blogDir, \"page.tsx\")],\n [\"changelog/release-list.tsx.tpl\", join(voxxDir, \"release-list.tsx\")],\n [\"shared/theme-toggle.tsx.tpl\", join(voxxDir, \"theme-toggle.tsx\")],\n );\n } else {\n templated.push(\n [\"blog/page.tsx.tpl\", join(blogDir, \"page.tsx\")],\n [\"blog/slug-page.tsx.tpl\", join(blogDir, \"[slug]\", \"page.tsx\")],\n [\"blog/post-page.tsx.tpl\", join(voxxDir, \"post-page.tsx\")],\n [\"blog/post-list.tsx.tpl\", join(voxxDir, \"post-list.tsx\")],\n [\"shared/theme-toggle.tsx.tpl\", join(voxxDir, \"theme-toggle.tsx\")],\n );\n }\n\n for (const [tpl, target, vars, siteWide] of templated) {\n const content = render(await readTemplate(tpl), vars ?? {});\n results.push([\n relative(cwd, target),\n await writeFileSafe(target, content, force),\n siteWide,\n ]);\n }\n\n cache = await enableCacheComponents(cwd, pkg);\n if (cache.kind === \"enabled\" || cache.kind === \"created\") {\n results.push([`${cache.file} (cacheComponents: true)`, \"written\"]);\n }\n }\n\n log.info(\"\");\n log.info(c.bold(add ? \"voxx init --add\" : \"voxx init\"));\n for (const [label, status, siteWide] of results) {\n const mark = status === \"written\" ? c.green(\"+\") : c.dim(\"•\");\n const note =\n status === \"skipped\"\n ? add && siteWide\n ? c.dim(\" (site-wide, already present)\")\n : c.dim(\" (exists, skipped)\")\n : \"\";\n const prefix = createdAppDir ? `${relative(process.cwd(), cwd)}/` : \"\";\n log.info(` ${mark} ${prefix}${label}${note}`);\n }\n\n log.info(\"\");\n log.info(c.bold(\"Next steps:\"));\n if (add) {\n log.info(\n ` 1. Write content in ${c.cyan(`${contentDir}/`)} (try ${c.cyan(`voxx new \"Title\" --collection ${collectionName}`)}).`,\n );\n if (hasNext && appDir) {\n log.info(` 2. Run your dev server and open ${c.cyan(basePath)}.`);\n } else if (hasNext) {\n log.warn(\n \"Next.js found but no app/ directory — pass --app <dir> to scaffold routes.\",\n );\n } else {\n log.info(\n ` 2. Run ${c.cyan(\"voxx build\")} to render static HTML to ${c.cyan(\"./dist\")}.`,\n );\n }\n log.info(\n ` ${c.dim('(Feature defaults like rss/toc follow the first collection\\'s type — review \"features\" in voxx.json.)')}`,\n );\n log.info(\"\");\n return;\n }\n if (staticChoice) {\n const writeHint =\n preset === \"docs\"\n ? `Write pages in ${c.cyan(`${contentDir}/`)} — folders become sections.`\n : preset === \"changelog\"\n ? `Add releases in ${c.cyan(`${contentDir}/`)} (try ${c.cyan('voxx new \"0.2.0\"')}).`\n : `Write posts in ${c.cyan(`${contentDir}/`)} (try ${c.cyan('voxx new \"My post\"')}).`;\n log.info(` 1. ${writeHint}`);\n log.info(` 2. Set ${c.cyan(\"site.url\")} in ${c.cyan(\"voxx.json\")}.`);\n log.info(\n ` 3. Run ${c.cyan(\"voxx build\")} to render static HTML to ${c.cyan(\"./dist\")}.`,\n );\n } else if (!hasNext) {\n log.warn(\"No Next.js detected — wrote voxx.json + sample content only.\");\n log.info(` Install the engine: ${c.cyan(\"npm i @prudentbird/voxx-core\")}`);\n log.info(` Or build static HTML: ${c.cyan(\"npx @prudentbird/voxx build\")}`);\n } else if (!appDir) {\n log.warn(\n \"Next.js found but no app/ directory — pass --app <dir> to scaffold routes.\",\n );\n } else {\n let step = 1;\n if (createdAppDir) {\n log.info(\n ` ${step++}. ${c.cyan(`cd ${relative(process.cwd(), createdAppDir)}`)}`,\n );\n }\n log.info(` ${step++}. Install the engine: ${c.cyan(\"npm i @prudentbird/voxx-core\")}`);\n if (cache?.kind === \"manual\") {\n log.info(\n ` ${step++}. Enable Cache Components — add ${c.cyan(\"cacheComponents: true\")} to next.config.`,\n );\n } else if (cache?.kind === \"unsupported\") {\n log.info(\n ` ${step++}. Upgrade to Next 16+ and add ${c.cyan(\"cacheComponents: true\")} to next.config.`,\n );\n }\n log.info(\n ` ${step++}. Set ${c.cyan(\"site.url\")} in ${c.cyan(\"voxx.json\")}.`,\n );\n log.info(` ${step}. Run your dev server and open ${c.cyan(basePath)}.`);\n if (cache?.kind === \"already\") {\n log.info(\n ` ${c.dim(`(Cache Components already enabled in ${cache.file}.)`)}`,\n );\n }\n if (wroteGlobals) {\n log.info(\n ` ${c.dim(\"(No design tokens found — added voxx-globals.css so it looks good out of the box.)\")}`,\n );\n }\n if (preset === \"docs\" && !createdAppDir && appDir) {\n log.info(\n ` ${c.dim(`(Heads up: your root layout wraps ${basePath} — its navbar/footer will show there too. To isolate the docs, see https://voxx.prudentbird.com/docs/reference/layouts.)`)}`,\n );\n }\n }\n log.info(\"\");\n}\n","import { copyFile, mkdir, readdir, writeFile } from \"node:fs/promises\";\nimport type { Dirent } from \"node:fs\";\nimport { dirname, join, relative, sep } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport {\n buildNavTree,\n buildSeo,\n escapeXml as esc,\n formatDate,\n getPosts,\n humanize,\n loadConfig,\n renderLlmsFull,\n renderLlmsTxtSections,\n renderRobotsTxt,\n renderRss,\n renderSitemap,\n rssPath,\n sectionHeading,\n serializeJsonLd,\n type CollectionConfig,\n type NavNode,\n type Post,\n type SeoData,\n type VoxxConfig,\n} from \"@prudentbird/voxx-core\";\nimport { c, exists, log, resolveCoreAsset } from \"../util\";\n\nfunction stripLead(path: string): string {\n return path.replace(/^\\/+/, \"\");\n}\n\nfunction headTags(seo: SeoData, config: VoxxConfig): string {\n const tags: string[] = [\n `<meta name=\"description\" content=\"${esc(seo.description)}\">`,\n `<link rel=\"canonical\" href=\"${esc(seo.canonical)}\">`,\n ];\n const og = seo.openGraph;\n if (og) {\n tags.push(\n `<meta property=\"og:type\" content=\"article\">`,\n `<meta property=\"og:title\" content=\"${esc(og.title)}\">`,\n `<meta property=\"og:description\" content=\"${esc(og.description)}\">`,\n `<meta property=\"og:url\" content=\"${esc(og.url)}\">`,\n `<meta property=\"og:site_name\" content=\"${esc(og.siteName)}\">`,\n ...og.images.map(\n (src) => `<meta property=\"og:image\" content=\"${esc(src)}\">`,\n ),\n );\n }\n if (seo.twitter) {\n tags.push(\n `<meta name=\"twitter:card\" content=\"summary_large_image\">`,\n `<meta name=\"twitter:title\" content=\"${esc(seo.twitter.title)}\">`,\n `<meta name=\"twitter:description\" content=\"${esc(seo.twitter.description)}\">`,\n );\n }\n if (config.seo.jsonLd && seo.jsonLd) {\n tags.push(\n `<script type=\"application/ld+json\">${serializeJsonLd(seo.jsonLd)}</script>`,\n );\n }\n return tags.join(\"\\n \");\n}\n\nfunction shell(opts: {\n title: string;\n lang: string;\n head: string;\n body: string;\n}): string {\n return `<!doctype html>\n<html lang=\"${esc(opts.lang)}\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>${esc(opts.title)}</title>\n <link rel=\"stylesheet\" href=\"/_voxx/voxx-globals.css\">\n <link rel=\"stylesheet\" href=\"/_voxx/voxx.css\">\n ${opts.head}\n </head>\n <body>\n${opts.body}\n </body>\n</html>\n`;\n}\n\nfunction siteHeader(config: VoxxConfig): string {\n const base = config.site.titleHref ?? \"/\";\n const rssIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\"><path d=\"M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"/><circle cx=\"5\" cy=\"19\" r=\"1\" fill=\"currentColor\"/></svg>`;\n const rss = config.features.rss\n ? `<div class=\"voxx-header__actions\"><a class=\"voxx-icon-button\" href=\"${esc(rssPath(config))}\" aria-label=\"RSS feed\">${rssIcon}</a></div>`\n : \"\";\n return ` <header class=\"voxx voxx-header\">\n <a class=\"voxx-header__title\" href=\"${esc(base)}\">${esc(config.site.title)}</a>\n ${rss}\n </header>`;\n}\n\nfunction metaLine(post: Post, config: VoxxConfig): string {\n const rt = config.features.readingTime\n ? ` · ${post.readingTimeMinutes} min read`\n : \"\";\n return `<time datetime=\"${esc(post.date)}\">${esc(formatDate(post.date, config.site.locale))}</time>${esc(rt)}`;\n}\n\nfunction tocAside(post: Post): string {\n if (post.toc.length === 0) return \"\";\n const items = post.toc\n .map(\n (t) =>\n ` <li class=\"voxx-toc__item\" data-depth=\"${t.depth}\"><a href=\"#${esc(t.id)}\">${esc(t.text)}</a></li>`,\n )\n .join(\"\\n\");\n return ` <aside class=\"voxx-aside\"><div class=\"voxx-aside__inner\">\n <nav class=\"voxx-toc\" aria-label=\"On this page\">\n <p class=\"voxx-toc__title\"><svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><path d=\"M2.5 4h7M2.5 8h11M2.5 12h7\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/></svg>On this page</p>\n <ul class=\"voxx-toc__list\">\n${items}\n </ul>\n </nav>\n </div></aside>`;\n}\n\nfunction indexBody(posts: Post[], config: VoxxConfig): string {\n const cards =\n posts.length === 0\n ? `<p class=\"voxx-empty\">No posts yet.</p>`\n : `<ul class=\"voxx-postlist\">\n${posts\n .map((post) => {\n const tags =\n config.features.tags && post.tags.length\n ? `<ul class=\"voxx-tags\">${post.tags.map((t) => `<li class=\"voxx-tag\">${esc(t)}</li>`).join(\"\")}</ul>`\n : \"\";\n const excerpt = post.excerpt\n ? `<p class=\"voxx-postcard__excerpt\">${esc(post.excerpt)}</p>`\n : \"\";\n return ` <li class=\"voxx-postcard\"><a class=\"voxx-postcard__link\" href=\"${esc(post.url)}\">\n <h2 class=\"voxx-postcard__title\">${esc(post.title)}</h2>\n <p class=\"voxx-postcard__meta\">${metaLine(post, config)}</p>\n ${excerpt}\n ${tags}\n </a></li>`;\n })\n .join(\"\\n\")}\n </ul>`;\n\n return ` <main class=\"voxx voxx-index\">\n <header class=\"voxx-index__header\">\n <h1>${esc(config.site.title)}</h1>\n ${config.site.description ? `<p class=\"voxx-index__desc\">${esc(config.site.description)}</p>` : \"\"}\n </header>\n ${cards}\n </main>`;\n}\n\nfunction backLink(config: VoxxConfig): string {\n const href = config.content.basePath || \"/\";\n const arrow = `<svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\"><path d=\"M10 12 6 8l4-4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/></svg>`;\n return `<a class=\"voxx-article__back\" href=\"${esc(href)}\">${arrow}All posts</a>`;\n}\n\nfunction postBody(post: Post, config: VoxxConfig): string {\n const aside = config.features.toc ? tocAside(post) : \"\";\n return ` <main class=\"voxx voxx-layout\">\n <article class=\"voxx-article\">\n ${backLink(config)}\n <header class=\"voxx-article__header\">\n <h1>${esc(post.title)}</h1>\n <p class=\"voxx-article__meta\">${metaLine(post, config)}</p>\n </header>\n <div class=\"voxx-prose\">${post.html}</div>\n </article>\n${aside}\n </main>`;\n}\n\nfunction navHtml(items: NavNode[], activeUrl: string): string {\n if (items.length === 0) return \"\";\n const lis = items\n .map((item) => {\n const label = item.url\n ? `<a class=\"voxx-nav__link\" href=\"${esc(item.url)}\"${item.url === activeUrl ? ' data-active=\"true\"' : \"\"}>${esc(item.title)}</a>`\n : `<span class=\"voxx-nav__section\">${esc(item.title)}</span>`;\n return `<li>${label}${navHtml(item.children, activeUrl)}</li>`;\n })\n .join(\"\\n\");\n return `<ul class=\"voxx-nav__list\">\\n${lis}\\n</ul>`;\n}\n\nfunction pagerHtml(prev: Post | undefined, next: Post | undefined): string {\n if (!prev && !next) return \"\";\n const link = (post: Post, label: string, cls: string) =>\n `<a class=\"voxx-pager__link${cls}\" href=\"${esc(post.url)}\"><span class=\"voxx-pager__label\">${label}</span><span class=\"voxx-pager__title\">${esc(post.title)}</span></a>`;\n return ` <nav class=\"voxx-pager\">\n ${prev ? link(prev, \"Previous\", \"\") : \"<span></span>\"}\n ${next ? link(next, \"Next\", \" voxx-pager__link--next\") : \"<span></span>\"}\n </nav>`;\n}\n\nfunction docsSidebar(\n nav: NavNode[],\n activeUrl: string,\n config: VoxxConfig,\n): string {\n const base = config.site.titleHref ?? \"/\";\n const menuIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/><path d=\"M9 3v18\"/></svg>`;\n return `<aside class=\"voxx-docs__nav\"><div class=\"voxx-docs__nav-inner\">\n <div class=\"voxx-docs__nav-header\">\n <details class=\"voxx-docs__menu\"><summary aria-label=\"Navigation\">${menuIcon}</summary>\n <div class=\"voxx-docs__menu-panel\"><nav class=\"voxx-nav\">${navHtml(nav, activeUrl)}</nav></div>\n </details>\n <a class=\"voxx-docs__title\" href=\"${esc(base)}\">${esc(config.site.title)}</a>\n </div>\n <nav class=\"voxx-nav\">${navHtml(nav, activeUrl)}</nav>\n </div></aside>`;\n}\n\nfunction docBody(\n post: Post,\n posts: Post[],\n index: number,\n nav: NavNode[],\n config: VoxxConfig,\n): string {\n const prev = index > 0 ? posts[index - 1] : undefined;\n const next = posts[index + 1];\n const aside = config.features.toc ? tocAside(post) : \"\";\n const desc = post.description\n ? `<p class=\"voxx-article__meta\">${esc(post.description)}</p>`\n : \"\";\n\n return ` <div class=\"voxx voxx-docs\">\n ${docsSidebar(nav, post.url, config)}\n <main class=\"voxx-layout\">\n <article class=\"voxx-article\">\n <header class=\"voxx-article__header\">\n <h1>${esc(post.title)}</h1>\n ${desc}\n </header>\n <div class=\"voxx-prose\">${post.html}</div>\n${pagerHtml(prev, next)}\n </article>\n${aside}\n </main>\n </div>`;\n}\n\nfunction docsIndexBody(nav: NavNode[], config: VoxxConfig): string {\n return ` <div class=\"voxx voxx-docs\">\n ${docsSidebar(nav, \"\", config)}\n <main class=\"voxx-layout\">\n <article class=\"voxx-article\">\n <header class=\"voxx-article__header\">\n <h1>${esc(config.site.title)}</h1>\n ${config.site.description ? `<p class=\"voxx-article__meta\">${esc(config.site.description)}</p>` : \"\"}\n </header>\n <div class=\"voxx-prose\">${navHtml(nav, \"\")}</div>\n </article>\n </main>\n </div>`;\n}\n\nfunction changelogBody(posts: Post[], config: VoxxConfig): string {\n const releases =\n posts.length === 0\n ? `<p class=\"voxx-empty\">No releases yet.</p>`\n : `<div class=\"voxx-releases\">\n${posts\n .map(\n (post) => ` <section class=\"voxx-release\" id=\"${esc(post.slug)}\">\n <header class=\"voxx-release__header\">\n <h2 class=\"voxx-release__version\"><a href=\"#${esc(post.slug)}\">${esc(post.version ? `v${post.version}` : post.title)}</a></h2>\n <time datetime=\"${esc(post.date)}\">${esc(formatDate(post.date, config.site.locale))}</time>\n </header>\n <div class=\"voxx-prose\">${post.html}</div>\n </section>`,\n )\n .join(\"\\n\")}\n </div>`;\n\n return ` <main class=\"voxx voxx-index\">\n <header class=\"voxx-index__header\">\n <h1>${esc(config.site.title)}</h1>\n ${config.site.description ? `<p class=\"voxx-index__desc\">${esc(config.site.description)}</p>` : \"\"}\n </header>\n ${releases}\n </main>`;\n}\n\n/**\n * Rewrite root-absolute internal links (`href`/`src` beginning with a single\n * `/`) to paths relative to the page's own location. This keeps navigation and\n * asset links working whether the generated site is served from the domain\n * root, a subpath, or opened directly from the filesystem. Protocol-relative\n * (`//host`) and external URLs are left untouched.\n */\nfunction relativizeLinks(\n html: string,\n fromDir: string,\n outDir: string,\n): string {\n const prefix = relative(fromDir, outDir).split(sep).join(\"/\") || \".\";\n return html.replace(/\\b(href|src)=\"\\/(?!\\/)([^\"]*)\"/g, `$1=\"${prefix}/$2\"`);\n}\n\nasync function writePage(\n path: string,\n html: string,\n outDir: string,\n): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n const out = path.endsWith(\".html\")\n ? relativizeLinks(html, dirname(path), outDir)\n : html;\n await writeFile(path, out);\n}\n\nconst SOURCE_RE = /\\.mdx?$/;\n\nasync function copyContentAssets(\n contentDir: string,\n targetDir: string,\n): Promise<number> {\n let copied = 0;\n let entries: Dirent[];\n try {\n entries = await readdir(contentDir, {\n recursive: true,\n withFileTypes: true,\n });\n } catch {\n return 0;\n }\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n const name = entry.name;\n if (SOURCE_RE.test(name) || name.startsWith(\".\")) continue;\n const rel = relative(contentDir, join(entry.parentPath, name));\n const source = join(contentDir, rel);\n const target = join(targetDir, rel);\n await mkdir(dirname(target), { recursive: true });\n await copyFile(source, target);\n copied++;\n }\n return copied;\n}\n\nasync function buildCollection(\n config: VoxxConfig,\n posts: Post[],\n outDir: string,\n): Promise<void> {\n const type = config.content.type;\n const indexPath = join(\n outDir,\n stripLead(config.content.basePath),\n \"index.html\",\n );\n\n if (type === \"changelog\") {\n await writePage(\n indexPath,\n shell({\n title: config.site.title,\n lang: config.site.locale,\n head: `<meta name=\"description\" content=\"${esc(config.site.description)}\">`,\n body: `${siteHeader(config)}\\n${changelogBody(posts, config)}`,\n }),\n outDir,\n );\n } else if (type === \"docs\") {\n const nav = buildNavTree(posts);\n for (let i = 0; i < posts.length; i++) {\n const post = posts[i]!;\n const seo = buildSeo(post, config);\n await writePage(\n join(outDir, stripLead(post.url), \"index.html\"),\n shell({\n title: `${post.title} — ${config.site.title}`,\n lang: config.site.locale,\n head: headTags(seo, config),\n body: docBody(post, posts, i, nav, config),\n }),\n outDir,\n );\n }\n if (!posts.some((p) => p.path.length === 0)) {\n await writePage(\n indexPath,\n shell({\n title: config.site.title,\n lang: config.site.locale,\n head: `<meta name=\"description\" content=\"${esc(config.site.description)}\">`,\n body: docsIndexBody(nav, config),\n }),\n outDir,\n );\n }\n } else {\n await writePage(\n indexPath,\n shell({\n title: config.site.title,\n lang: config.site.locale,\n head: `<meta name=\"description\" content=\"${esc(config.site.description)}\">`,\n body: `${siteHeader(config)}\\n${indexBody(posts, config)}`,\n }),\n outDir,\n );\n\n for (const post of posts) {\n const seo = buildSeo(post, config);\n await writePage(\n join(outDir, stripLead(post.url), \"index.html\"),\n shell({\n title: `${post.title} — ${config.site.title}`,\n lang: config.site.locale,\n head: headTags(seo, config),\n body: `${siteHeader(config)}\\n${postBody(post, config)}`,\n }),\n outDir,\n );\n }\n }\n}\n\nexport interface BuildSiteOptions {\n cwd: string;\n outDir: string;\n includeDrafts?: boolean | undefined;\n quiet?: boolean;\n}\n\nexport interface BuildSiteResult {\n config: VoxxConfig;\n pageCount: number;\n collectionCount: number;\n indexRel: string;\n}\n\nexport async function buildSite(\n opts: BuildSiteOptions,\n): Promise<BuildSiteResult> {\n const { cwd, outDir } = opts;\n const config = await loadConfig({ cwd });\n const collections = config.collections;\n const multi = collections.length > 1;\n\n await mkdir(join(outDir, \"_voxx\"), { recursive: true });\n await copyFile(\n resolveCoreAsset(\"theme/voxx.css\"),\n join(outDir, \"_voxx\", \"voxx.css\"),\n );\n await copyFile(\n resolveCoreAsset(\"theme/demo-globals.css\"),\n join(outDir, \"_voxx\", \"voxx-globals.css\"),\n );\n\n const allPosts: Post[] = [];\n const sections: Array<{ heading: string; posts: Post[] }> = [];\n let pageCount = 0;\n\n for (const collection of collections) {\n const view: VoxxConfig = { ...config, content: { ...collection } };\n const posts = await getPosts({\n config: view,\n includeDrafts: opts.includeDrafts,\n });\n await buildCollection(view, posts, outDir);\n const assetTarget = join(outDir, stripLead(collection.basePath));\n await copyContentAssets(collection.dir, assetTarget);\n\n if (config.features.rss && isFeedType(collection)) {\n await writePage(\n join(outDir, stripLead(rssPath(view))),\n renderRss(posts, view),\n outDir,\n );\n }\n\n sections.push({\n heading: multi\n ? humanize(collection.name)\n : sectionHeading(collection.type),\n posts,\n });\n allPosts.push(...posts);\n pageCount += posts.length;\n }\n\n if (config.features.sitemap) {\n await writeFile(\n join(outDir, \"sitemap.xml\"),\n renderSitemap(allPosts, config, {\n indexPaths: collections.map((col) => col.basePath),\n }),\n );\n await writeFile(join(outDir, \"robots.txt\"), renderRobotsTxt(config));\n }\n if (config.features.llmsTxt) {\n await writeFile(\n join(outDir, \"llms.txt\"),\n renderLlmsTxtSections(sections, config),\n );\n await writeFile(\n join(outDir, \"llms-full.txt\"),\n renderLlmsFull(allPosts, config),\n );\n }\n\n return {\n config,\n pageCount,\n collectionCount: collections.length,\n indexRel: join(\n relative(cwd, outDir),\n stripLead(collections[0]!.basePath),\n \"index.html\",\n ),\n };\n}\n\nfunction isFeedType(collection: CollectionConfig): boolean {\n return collection.type === \"blog\" || collection.type === \"changelog\";\n}\n\nexport async function build(argv: string[]): Promise<void> {\n const { values } = parseArgs({\n args: argv,\n options: {\n out: { type: \"string\" },\n drafts: { type: \"boolean\" },\n },\n allowPositionals: true,\n });\n\n const cwd = process.cwd();\n if (!(await exists(join(cwd, \"voxx.json\")))) {\n log.error(\"No voxx.json found. Run `voxx init` first.\");\n process.exitCode = 1;\n return;\n }\n\n const outDir = join(cwd, values.out ?? \"dist\");\n const result = await buildSite({\n cwd,\n outDir,\n includeDrafts: values.drafts ? true : undefined,\n });\n\n const { config } = result;\n if (!config.site.url || /example\\.com/.test(config.site.url)) {\n log.warn(\n `site.url is ${config.site.url ? `\"${config.site.url}\"` : \"empty\"} — feeds, sitemap, and SEO tags need the real production URL in voxx.json.`,\n );\n }\n\n const servesRoot = config.collections.some(\n (col) => stripLead(col.basePath) === \"\",\n );\n if (config.site.titleHref === undefined && !servesRoot) {\n log.warn(\n `The title link defaults to \"/\", but nothing is generated there (no collection uses basePath \"/\"). Set site.titleHref in voxx.json — e.g. \"${config.collections[0]!.basePath}\" to point at the index, or your parent site's home if this is embedded under a larger site.`,\n );\n }\n\n const type = config.content.type;\n const noun =\n type === \"changelog\" ? \"release\" : type === \"docs\" ? \"page\" : \"post\";\n const what =\n result.collectionCount > 1\n ? `${result.pageCount} pages across ${result.collectionCount} collections`\n : `${result.pageCount} ${noun}${result.pageCount === 1 ? \"\" : \"s\"}`;\n log.success(`Built ${what} → ${relative(cwd, outDir)}/`);\n log.info(\n ` Open ${c.cyan(result.indexRel)} in a browser, or run ${c.cyan(\"voxx dev\")} to preview with a local server.`,\n );\n}\n","import { watch, type FSWatcher } from \"node:fs\";\nimport { mkdtemp, readFile, rm } from \"node:fs/promises\";\nimport { createServer } from \"node:http\";\nimport { tmpdir } from \"node:os\";\nimport { extname, join, normalize } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { loadConfig } from \"@prudentbird/voxx-core\";\nimport { c, exists, log } from \"../util\";\nimport { buildSite } from \"./build\";\n\nconst MIME: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".js\": \"text/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".xml\": \"application/xml; charset=utf-8\",\n \".txt\": \"text/plain; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".avif\": \"image/avif\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".pdf\": \"application/pdf\",\n};\n\nexport interface DevHandle {\n port: number;\n close: () => Promise<void>;\n}\n\nexport async function serveFile(outDir: string, urlPath: string) {\n const decoded = decodeURIComponent(urlPath.split(\"?\")[0] ?? \"/\");\n const safe = normalize(decoded).replace(/^(\\.\\.[\\\\/])+/, \"\");\n const candidates = safe.endsWith(\"/\")\n ? [join(safe, \"index.html\")]\n : [safe, join(safe, \"index.html\")];\n for (const rel of candidates) {\n const path = join(outDir, rel);\n if (!path.startsWith(outDir)) continue;\n try {\n const body = await readFile(path);\n const type =\n MIME[extname(path).toLowerCase()] ?? \"application/octet-stream\";\n return { status: 200, type, body };\n } catch {}\n }\n return {\n status: 404,\n type: \"text/html; charset=utf-8\",\n body: Buffer.from(\"<h1>404</h1><p>Not found.</p>\"),\n };\n}\n\nexport async function dev(argv: string[]): Promise<DevHandle | undefined> {\n const { values } = parseArgs({\n args: argv,\n options: {\n port: { type: \"string\" },\n drafts: { type: \"boolean\" },\n },\n allowPositionals: true,\n });\n\n const cwd = process.cwd();\n if (!(await exists(join(cwd, \"voxx.json\")))) {\n log.error(\"No voxx.json found. Run `voxx init` first.\");\n process.exitCode = 1;\n return;\n }\n\n const port = Number(values.port ?? 4321);\n if (!Number.isInteger(port) || port <= 0 || port > 65535) {\n log.error(`Invalid port \"${values.port}\".`);\n process.exitCode = 1;\n return;\n }\n\n const includeDrafts = values.drafts ?? true;\n const outDir = await mkdtemp(join(tmpdir(), \"voxx-dev-\"));\n\n let building = Promise.resolve();\n let dirty = false;\n const rebuild = (label: string) => {\n building = building.then(async () => {\n try {\n const started = Date.now();\n const result = await buildSite({ cwd, outDir, includeDrafts });\n log.success(\n `${label} — ${result.pageCount} pages in ${Date.now() - started}ms`,\n );\n } catch (err) {\n log.error(err instanceof Error ? err.message : String(err));\n }\n });\n return building;\n };\n\n await rebuild(\"Built\");\n\n const watchers: FSWatcher[] = [];\n const watchPath = (path: string, recursive: boolean) => {\n try {\n const watcher = watch(path, { recursive }, () => {\n if (dirty) return;\n dirty = true;\n setTimeout(() => {\n dirty = false;\n void rebuild(\"Rebuilt\");\n }, 150);\n });\n watchers.push(watcher);\n } catch {\n log.warn(`Could not watch ${path}.`);\n }\n };\n\n const config = await loadConfig({ cwd });\n watchPath(join(cwd, \"voxx.json\"), false);\n for (const collection of config.collections) {\n if (await exists(collection.dir)) watchPath(collection.dir, true);\n }\n\n const server = createServer((req, res) => {\n building\n .then(() => serveFile(outDir, req.url ?? \"/\"))\n .then(({ status, type, body }) => {\n res.writeHead(status, {\n \"Content-Type\": type,\n \"Cache-Control\": \"no-store\",\n });\n res.end(body);\n })\n .catch((err: unknown) => {\n log.error(err instanceof Error ? err.message : String(err));\n if (!res.headersSent) {\n res.writeHead(500, { \"Content-Type\": \"text/plain\" });\n }\n res.end(\"Internal error\");\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(port, resolve);\n }).catch((err: NodeJS.ErrnoException) => {\n log.error(\n err.code === \"EADDRINUSE\"\n ? `Port ${port} is in use — pass --port <n>.`\n : err.message,\n );\n process.exitCode = 1;\n });\n if (process.exitCode === 1) return;\n\n const base = config.collections[0]!.basePath;\n log.info(\"\");\n log.success(`voxx dev serving ${c.cyan(`http://localhost:${port}${base}`)}`);\n log.info(\n ` Watching content for changes${includeDrafts ? \" (drafts included)\" : \"\"}. Press Ctrl+C to stop.`,\n );\n\n const close = () =>\n new Promise<void>((resolve) => {\n for (const watcher of watchers) watcher.close();\n server.close(() => {\n void rm(outDir, { recursive: true, force: true }).finally(resolve);\n });\n });\n\n const shutdown = () => {\n void close().then(() => process.exit(0));\n };\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n return { port, close };\n}\n","import { readFile, readdir } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport { parseArgs } from \"node:util\";\nimport {\n parseVersion,\n resolveCollectionDefaults,\n slugify,\n splitDatePrefix,\n splitOrderPrefix,\n} from \"@prudentbird/voxx-core\";\nimport { exists, isSafeRelPath, log, writeFileSafe, yamlValue } from \"../util\";\n\nconst MD_RE = /\\.md$/;\n\ntype ContentType = \"blog\" | \"docs\" | \"changelog\";\n\ninterface VoxxJson {\n content?: { type?: ContentType; dir?: string };\n collections?: Array<{ name?: string; type?: ContentType; dir?: string }>;\n}\n\nasync function readContentConfig(\n cwd: string,\n collectionName?: string,\n): Promise<{ type: ContentType; dir: string } | undefined> {\n const cfgPath = join(cwd, \"voxx.json\");\n if (!(await exists(cfgPath))) return { type: \"blog\", dir: \"content\" };\n const cfg = JSON.parse(await readFile(cfgPath, \"utf8\")) as VoxxJson;\n const collections = (cfg.collections ?? []).map(resolveCollectionDefaults);\n if (collectionName) {\n const found = collections.find((c) => c.name === collectionName);\n if (!found) {\n log.error(\n `Unknown collection \"${collectionName}\" — defined: ${collections.map((c) => c.name).join(\", \")}`,\n );\n return undefined;\n }\n return found;\n }\n const first = collections[0] ?? {\n type: cfg.content?.type ?? \"blog\",\n dir: cfg.content?.dir ?? \"content\",\n };\n return { type: first.type, dir: first.dir };\n}\n\nasync function existingSlugs(dir: string): Promise<Set<string>> {\n const slugs = new Set<string>();\n try {\n for (const entry of await readdir(dir)) {\n if (!MD_RE.test(entry)) continue;\n const { rest } = splitDatePrefix(entry.replace(MD_RE, \"\"));\n slugs.add(slugify(splitOrderPrefix(rest).rest));\n }\n } catch {}\n return slugs;\n}\n\nfunction suggestSlug(base: string, taken: Set<string>): string {\n let slug = base;\n for (let n = 2; taken.has(slug); n++) slug = `${base}-${n}`;\n return slug;\n}\n\nasync function resolveSlug(base: string, taken: Set<string>): Promise<string> {\n if (!taken.has(base)) return base;\n\n let suggestion = suggestSlug(base, taken);\n if (!process.stdin.isTTY) {\n log.warn(`Slug \"${base}\" is taken — using \"${suggestion}\".`);\n return suggestion;\n }\n\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n try {\n let takenName = base;\n for (;;) {\n const answer = (\n await rl.question(\n `Slug \"${takenName}\" is taken. Enter a new slug, or press Enter for \"${suggestion}\": `,\n )\n ).trim();\n if (!answer) return suggestion;\n\n const candidate = slugify(answer);\n if (!candidate) {\n log.warn(\"Please enter a valid slug.\");\n continue;\n }\n if (!taken.has(candidate)) return candidate;\n\n log.warn(`\"${candidate}\" is also taken.`);\n takenName = candidate;\n suggestion = suggestSlug(candidate, taken);\n }\n } finally {\n rl.close();\n }\n}\n\nexport async function newPost(argv: string[]): Promise<void> {\n const { values, positionals } = parseArgs({\n args: argv,\n options: {\n dir: { type: \"string\" },\n date: { type: \"string\" },\n slug: { type: \"string\" },\n flat: { type: \"boolean\" },\n section: { type: \"string\" },\n order: { type: \"string\" },\n collection: { type: \"string\" },\n index: { type: \"boolean\" },\n },\n allowPositionals: true,\n });\n\n const title = positionals.join(\" \").trim();\n if (!title) {\n log.error('Usage: voxx new \"My Post Title\"');\n process.exitCode = 1;\n return;\n }\n\n const cwd = process.cwd();\n const detected = await readContentConfig(cwd, values.collection);\n if (!detected) {\n process.exitCode = 1;\n return;\n }\n const contentDir = values.dir ?? detected.dir;\n if (!isSafeRelPath(contentDir)) {\n log.error(\n `Invalid --dir \"${contentDir}\" — must stay within the project (no \"..\").`,\n );\n process.exitCode = 1;\n return;\n }\n if (values.index && detected.type !== \"docs\") {\n log.error(\"--index only applies to docs content.\");\n process.exitCode = 1;\n return;\n }\n const date = values.date ?? new Date().toISOString().slice(0, 10);\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n log.error(`Invalid --date \"${values.date}\" — expected YYYY-MM-DD.`);\n process.exitCode = 1;\n return;\n }\n\n if (detected.type === \"changelog\") {\n const version = parseVersion(title) ?? title;\n if (\n !isSafeRelPath(`${version}.md`) ||\n version.includes(\"/\") ||\n version.includes(\"\\\\\")\n ) {\n log.error(\n `Invalid changelog name \"${title}\" — use a version like \"1.2.0\".`,\n );\n process.exitCode = 1;\n return;\n }\n const target = join(cwd, contentDir, `${version}.md`);\n const body = [\n \"---\",\n `title: ${yamlValue(`v${version}`)}`,\n `version: ${yamlValue(version)}`,\n `date: ${date}`,\n \"---\",\n \"\",\n \"### Added\",\n \"\",\n \"- \",\n \"\",\n ].join(\"\\n\");\n const status = await writeFileSafe(target, body, false);\n if (status === \"skipped\") {\n log.warn(`${relative(cwd, target)} already exists — left untouched.`);\n } else {\n log.success(`Created ${relative(cwd, target)}`);\n }\n return;\n }\n\n const baseSlug = slugify(values.slug ?? title);\n if (!baseSlug) {\n log.error(\"Could not derive a slug — pass --slug.\");\n process.exitCode = 1;\n return;\n }\n\n if (detected.type === \"docs\") {\n if (values.section && !isSafeRelPath(values.section)) {\n log.error(\n `Invalid --section \"${values.section}\" — must stay within the content directory (no \"..\").`,\n );\n process.exitCode = 1;\n return;\n }\n const section = (values.section ?? \"\").split(\"/\").filter(Boolean).join(\"/\");\n const targetDir = section\n ? join(cwd, contentDir, section)\n : join(cwd, contentDir);\n if (values.index) {\n const target = join(targetDir, \"index.md\");\n const body = [\n \"---\",\n `title: ${yamlValue(title)}`,\n \"description: \",\n \"---\",\n \"\",\n \"Write your section landing page here.\",\n \"\",\n ].join(\"\\n\");\n const status = await writeFileSafe(target, body, false);\n if (status === \"skipped\") {\n log.warn(`${relative(cwd, target)} already exists — left untouched.`);\n } else {\n log.success(`Created ${relative(cwd, target)}`);\n }\n return;\n }\n const taken = await existingSlugs(targetDir);\n const slug = await resolveSlug(baseSlug, taken);\n const order = values.order ? Number(values.order) : undefined;\n const fileName =\n order !== undefined && Number.isFinite(order)\n ? `${String(order).padStart(2, \"0\")}-${slug}.md`\n : `${slug}.md`;\n const target = join(targetDir, fileName);\n const body = [\n \"---\",\n `title: ${yamlValue(title)}`,\n \"description: \",\n \"---\",\n \"\",\n \"Write your page here.\",\n \"\",\n ].join(\"\\n\");\n const status = await writeFileSafe(target, body, false);\n if (status === \"skipped\") {\n log.warn(`${relative(cwd, target)} already exists — left untouched.`);\n } else {\n log.success(`Created ${relative(cwd, target)}`);\n }\n return;\n }\n\n const taken = await existingSlugs(join(cwd, contentDir));\n const slug = await resolveSlug(baseSlug, taken);\n\n const fileName = values.flat ? `${slug}.md` : `${date}-${slug}.md`;\n const target = join(cwd, contentDir, fileName);\n\n const body = [\n \"---\",\n `title: ${yamlValue(title)}`,\n \"description: \",\n `date: ${date}`,\n `slug: ${slug}`,\n \"tags: []\",\n \"---\",\n \"\",\n \"Write your post here.\",\n \"\",\n ].join(\"\\n\");\n\n const status = await writeFileSafe(target, body, false);\n if (status === \"skipped\") {\n log.warn(`${relative(cwd, target)} already exists — left untouched.`);\n } else {\n log.success(`Created ${relative(cwd, target)}`);\n }\n}\n","#!/usr/bin/env node\nimport { c, log } from \"./util\";\nimport { init } from \"./commands/init\";\nimport { build } from \"./commands/build\";\nimport { dev } from \"./commands/dev\";\nimport { newPost } from \"./commands/new\";\n\nconst HELP = `${c.bold(\"voxx\")} — a zero-friction, file-based CMS for blogs and docs\n\n${c.bold(\"Usage:\")}\n voxx init [blog|docs|changelog] [--dir <content>] [--base <path>] [--app <dir>] [--force]\n voxx init --add [blog|docs|changelog] [--name <name>] [--dir <dir>] [--base <path>] [--app <dir>]\n voxx new \"Title\" [--collection <name>] [--slug <slug>] [--dir <content>] [--date <YYYY-MM-DD>] [--flat] [--section <path>] [--order <n>] [--index]\n voxx build [--out <dir>] [--drafts]\n voxx dev [--port <n>] [--drafts]\n\n${c.bold(\"Examples:\")}\n voxx init Scaffold a blog into your Next.js app\n voxx init docs Scaffold a docs site instead\n voxx init changelog Scaffold a release-notes page\n voxx init --add docs Add a docs collection to an existing site\n voxx new \"Hello world\" Create a new markdown post (or doc page, or release)\n voxx new \"Guides\" --section guides --index Create a docs section's index.md landing page\n voxx build Render a static HTML site to ./dist\n voxx dev Preview the static site locally, rebuilding on change\n`;\n\nasync function main(): Promise<void> {\n const [cmd, ...rest] = process.argv.slice(2);\n switch (cmd) {\n case \"init\":\n await init(rest);\n break;\n case \"new\":\n await newPost(rest);\n break;\n case \"build\":\n await build(rest);\n break;\n case \"dev\":\n await dev(rest);\n break;\n case undefined:\n case \"-h\":\n case \"--help\":\n log.info(HELP);\n break;\n default:\n log.error(`Unknown command: ${cmd}`);\n log.info(HELP);\n process.exitCode = 1;\n }\n}\n\nmain().catch((err) => {\n log.error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n});\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prudentbird/voxx",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A zero-friction CMS for you and your agents. Write the way you ship code, and Voxx handles the rest.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "prudentbird <me@prudentbird.com> (https://prudentbird.com)",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"LICENSE"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@prudentbird/voxx-core": "1.
|
|
43
|
+
"@prudentbird/voxx-core": "1.1.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^25.9.3",
|
|
@@ -14,7 +14,7 @@ export default async function BlogLayout({
|
|
|
14
14
|
return (
|
|
15
15
|
<div className="voxx">
|
|
16
16
|
<header className="voxx-header">
|
|
17
|
-
<Link href="
|
|
17
|
+
<Link href={config.site.titleHref ?? "/"} className="voxx-header__title">
|
|
18
18
|
{config.site.title}
|
|
19
19
|
</Link>
|
|
20
20
|
<div className="voxx-header__actions">
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Post, VoxxConfig } from "@prudentbird/voxx-core";
|
|
2
|
+
import Link from "next/link";
|
|
2
3
|
import { OnThisPage } from "./on-this-page";
|
|
3
4
|
import { formatDate } from "@prudentbird/voxx-core";
|
|
4
5
|
|
|
@@ -14,6 +15,18 @@ export function PostPage({
|
|
|
14
15
|
return (
|
|
15
16
|
<div className="voxx voxx-layout">
|
|
16
17
|
<article className="voxx-article">
|
|
18
|
+
<Link href={config.content.basePath || "/"} className="voxx-article__back">
|
|
19
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
20
|
+
<path
|
|
21
|
+
d="M10 12 6 8l4-4"
|
|
22
|
+
stroke="currentColor"
|
|
23
|
+
strokeWidth="1.5"
|
|
24
|
+
strokeLinecap="round"
|
|
25
|
+
strokeLinejoin="round"
|
|
26
|
+
/>
|
|
27
|
+
</svg>
|
|
28
|
+
All posts
|
|
29
|
+
</Link>
|
|
17
30
|
<header className="voxx-article__header">
|
|
18
31
|
<h1>{post.title}</h1>
|
|
19
32
|
<p className="voxx-article__meta">
|
|
@@ -14,7 +14,7 @@ export default async function ChangelogLayout({
|
|
|
14
14
|
return (
|
|
15
15
|
<div className="voxx">
|
|
16
16
|
<header className="voxx-header">
|
|
17
|
-
<Link href="
|
|
17
|
+
<Link href={config.site.titleHref ?? "/"} className="voxx-header__title">
|
|
18
18
|
{config.site.title}
|
|
19
19
|
</Link>
|
|
20
20
|
<div className="voxx-header__actions">
|
|
@@ -34,7 +34,7 @@ export default async function DocsLayout({
|
|
|
34
34
|
<div className="voxx-docs__nav-inner">
|
|
35
35
|
<div className="voxx-docs__nav-header">
|
|
36
36
|
<MobileNav items={tree} title={config.site.title} />
|
|
37
|
-
<Link href="
|
|
37
|
+
<Link href={config.site.titleHref ?? "/"} className="voxx-docs__title">
|
|
38
38
|
{config.site.title}
|
|
39
39
|
</Link>
|
|
40
40
|
</div>
|
|
@@ -21,7 +21,7 @@ export default async function DocsLayout({
|
|
|
21
21
|
<div className="voxx-docs__nav-inner">
|
|
22
22
|
<div className="voxx-docs__nav-header">
|
|
23
23
|
<MobileNav items={tree} title={config.site.title} />
|
|
24
|
-
<Link href="
|
|
24
|
+
<Link href={config.site.titleHref ?? "/"} className="voxx-docs__title">
|
|
25
25
|
{config.site.title}
|
|
26
26
|
</Link>
|
|
27
27
|
</div>
|
|
@@ -5,7 +5,11 @@ import { getConfig } from "{{DATA_IMPORT}}";
|
|
|
5
5
|
export default async function robots(): Promise<MetadataRoute.Robots> {
|
|
6
6
|
const config = await getConfig();
|
|
7
7
|
return {
|
|
8
|
-
rules: {
|
|
8
|
+
rules: {
|
|
9
|
+
userAgent: "*",
|
|
10
|
+
allow: "/",
|
|
11
|
+
disallow: ["/_next/", "/api/"],
|
|
12
|
+
},
|
|
9
13
|
...(config.features.sitemap
|
|
10
14
|
? { sitemap: absoluteUrl(config.site.url, "/sitemap.xml") }
|
|
11
15
|
: {}),
|
|
@@ -11,13 +11,20 @@ export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
return [
|
|
14
|
-
{
|
|
15
|
-
|
|
14
|
+
{
|
|
15
|
+
url: config.site.url,
|
|
16
|
+
lastModified: index.lastModified,
|
|
17
|
+
changeFrequency: "weekly",
|
|
18
|
+
priority: 1.0,
|
|
19
|
+
},
|
|
20
|
+
{ ...index, changeFrequency: "weekly", priority: 0.9 },
|
|
16
21
|
...posts
|
|
17
22
|
.filter((post) => post.path.length > 0)
|
|
18
23
|
.map((post) => ({
|
|
19
24
|
url: absoluteUrl(config.site.url, post.url),
|
|
20
25
|
lastModified: post.updated ?? post.date,
|
|
26
|
+
changeFrequency: "weekly" as const,
|
|
27
|
+
priority: 0.7,
|
|
21
28
|
})),
|
|
22
29
|
];
|
|
23
30
|
}
|