@prudentbird/voxx 1.0.1 → 1.2.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 +1 -1
- package/dist/index.mjs +37 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- 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/data.ts.tpl +3 -0
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ npx @prudentbird/voxx init changelog # or a release-notes page
|
|
|
14
14
|
|
|
15
15
|
Scaffolds a surface into your app:
|
|
16
16
|
|
|
17
|
-
- **Next.js detected** — writes routes under `app/<basePath>/` (private `_voxx/` folder for the data layer and components — all yours to restyle), `rss.xml`/`llms.txt`/`llms-full.txt` routes plus a sitemap and `robots.ts` where the type calls for them, and
|
|
17
|
+
- **Next.js detected** — writes routes under `app/<basePath>/` (private `_voxx/` folder for the data layer and components — all yours to restyle), `rss.xml`/`llms.txt`/`llms-full.txt` routes plus a sitemap and `robots.ts` where the type calls for them, and wraps your next.config with `withVoxx` when it's safe to (Next 16+, recognizable config shape).
|
|
18
18
|
- **No Next.js** — asks whether you want a static site (`voxx build`) or a fresh app via `create-next-app`, then scaffolds into it.
|
|
19
19
|
|
|
20
20
|
Flags: `--base /notes` (mount path — routes follow it), `--dir content`, `--app src/app`, `--force`.
|
package/dist/index.mjs
CHANGED
|
@@ -259,15 +259,29 @@ function nextMajor(pkg) {
|
|
|
259
259
|
const m = /(\d+)/.exec(range);
|
|
260
260
|
return m ? Number(m[1]) : null;
|
|
261
261
|
}
|
|
262
|
+
const CORE_NEXT_IMPORT = "@prudentbird/voxx-core/next";
|
|
262
263
|
const MINIMAL_NEXT_CONFIG = `import type { NextConfig } from "next";
|
|
264
|
+
import { withVoxx } from "${CORE_NEXT_IMPORT}";
|
|
263
265
|
|
|
264
|
-
const nextConfig: NextConfig = {
|
|
265
|
-
cacheComponents: true,
|
|
266
|
-
};
|
|
266
|
+
const nextConfig: NextConfig = {};
|
|
267
267
|
|
|
268
|
-
export default nextConfig;
|
|
268
|
+
export default withVoxx(nextConfig);
|
|
269
269
|
`;
|
|
270
|
-
|
|
270
|
+
/**
|
|
271
|
+
* Wraps the default export of an existing next.config with `withVoxx`, adding
|
|
272
|
+
* the matching import. Returns `null` when no recognizable export is found.
|
|
273
|
+
*/
|
|
274
|
+
function wrapNextConfig(source) {
|
|
275
|
+
const esm = source.lastIndexOf("export default ");
|
|
276
|
+
if (esm !== -1) return `import { withVoxx } from "${CORE_NEXT_IMPORT}";\n${source.slice(0, esm)}export default withVoxx(${source.slice(esm + 15).replace(/;?\s*$/, "")});\n`;
|
|
277
|
+
const cjs = /module\.exports\s*=\s*/.exec(source);
|
|
278
|
+
if (cjs) {
|
|
279
|
+
const start = cjs.index + cjs[0].length;
|
|
280
|
+
return `const { withVoxx } = require("${CORE_NEXT_IMPORT}");\n${source.slice(0, start)}withVoxx(${source.slice(start).replace(/;?\s*$/, "")});\n`;
|
|
281
|
+
}
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
async function configureNextConfig(cwd, pkg) {
|
|
271
285
|
const major = nextMajor(pkg);
|
|
272
286
|
if (major !== null && major < 16) return { kind: "unsupported" };
|
|
273
287
|
let file = null;
|
|
@@ -284,18 +298,15 @@ async function enableCacheComponents(cwd, pkg) {
|
|
|
284
298
|
};
|
|
285
299
|
}
|
|
286
300
|
const source = await readFile(join(cwd, file), "utf8");
|
|
287
|
-
if (/\
|
|
301
|
+
if (/\bwithVoxx\b/.test(source)) return {
|
|
288
302
|
kind: "already",
|
|
289
303
|
file
|
|
290
304
|
};
|
|
291
|
-
const
|
|
292
|
-
if (
|
|
293
|
-
|
|
294
|
-
const rest = source.slice(at);
|
|
295
|
-
const insert = rest.trimStart().startsWith("}") ? "\n cacheComponents: true,\n" : "\n cacheComponents: true,";
|
|
296
|
-
await writeFile(join(cwd, file), source.slice(0, at) + insert + rest);
|
|
305
|
+
const wrapped = wrapNextConfig(source);
|
|
306
|
+
if (wrapped === null) return { kind: "manual" };
|
|
307
|
+
await writeFile(join(cwd, file), wrapped);
|
|
297
308
|
return {
|
|
298
|
-
kind: "
|
|
309
|
+
kind: "wrapped",
|
|
299
310
|
file
|
|
300
311
|
};
|
|
301
312
|
}
|
|
@@ -566,8 +577,8 @@ async function init(argv) {
|
|
|
566
577
|
siteWide
|
|
567
578
|
]);
|
|
568
579
|
}
|
|
569
|
-
cache = await
|
|
570
|
-
if (cache.kind === "
|
|
580
|
+
cache = await configureNextConfig(cwd, pkg);
|
|
581
|
+
if (cache.kind === "wrapped" || cache.kind === "created") results.push([`${cache.file} (wrapped with withVoxx)`, "written"]);
|
|
571
582
|
}
|
|
572
583
|
log.info("");
|
|
573
584
|
log.info(c.bold(add ? "voxx init --add" : "voxx init"));
|
|
@@ -602,11 +613,11 @@ async function init(argv) {
|
|
|
602
613
|
let step = 1;
|
|
603
614
|
if (createdAppDir) log.info(` ${step++}. ${c.cyan(`cd ${relative(process.cwd(), createdAppDir)}`)}`);
|
|
604
615
|
log.info(` ${step++}. Install the engine: ${c.cyan("npm i @prudentbird/voxx-core")}`);
|
|
605
|
-
if (cache?.kind === "manual") log.info(` ${step++}.
|
|
606
|
-
else if (cache?.kind === "unsupported") log.info(` ${step++}. Upgrade to Next 16
|
|
616
|
+
if (cache?.kind === "manual") log.info(` ${step++}. Wrap your config — ${c.cyan("export default withVoxx(nextConfig)")} from ${c.cyan(CORE_NEXT_IMPORT)}.`);
|
|
617
|
+
else if (cache?.kind === "unsupported") log.info(` ${step++}. Upgrade to Next 16+, then wrap your config with ${c.cyan("withVoxx")} from ${c.cyan(CORE_NEXT_IMPORT)}.`);
|
|
607
618
|
log.info(` ${step++}. Set ${c.cyan("site.url")} in ${c.cyan("voxx.json")}.`);
|
|
608
619
|
log.info(` ${step}. Run your dev server and open ${c.cyan(basePath)}.`);
|
|
609
|
-
if (cache?.kind === "already") log.info(` ${c.dim(`(
|
|
620
|
+
if (cache?.kind === "already") log.info(` ${c.dim(`(next.config already wrapped with withVoxx in ${cache.file}.)`)}`);
|
|
610
621
|
if (wroteGlobals) log.info(` ${c.dim("(No design tokens found — added voxx-globals.css so it looks good out of the box.)")}`);
|
|
611
622
|
if (preset === "docs" && !createdAppDir && appDir) log.info(` ${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.)`)}`);
|
|
612
623
|
}
|
|
@@ -643,7 +654,7 @@ ${opts.body}
|
|
|
643
654
|
`;
|
|
644
655
|
}
|
|
645
656
|
function siteHeader(config) {
|
|
646
|
-
const base = config.
|
|
657
|
+
const base = config.site.titleHref ?? "/";
|
|
647
658
|
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
659
|
return ` <header class="voxx voxx-header">
|
|
649
660
|
<a class="voxx-header__title" href="${escapeXml(base)}">${escapeXml(config.site.title)}</a>
|
|
@@ -686,10 +697,14 @@ ${posts.map((post) => {
|
|
|
686
697
|
${cards}
|
|
687
698
|
</main>`;
|
|
688
699
|
}
|
|
700
|
+
function backLink(config) {
|
|
701
|
+
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>`;
|
|
702
|
+
}
|
|
689
703
|
function postBody(post, config) {
|
|
690
704
|
const aside = config.features.toc ? tocAside(post) : "";
|
|
691
705
|
return ` <main class="voxx voxx-layout">
|
|
692
706
|
<article class="voxx-article">
|
|
707
|
+
${backLink(config)}
|
|
693
708
|
<header class="voxx-article__header">
|
|
694
709
|
<h1>${escapeXml(post.title)}</h1>
|
|
695
710
|
<p class="voxx-article__meta">${metaLine(post, config)}</p>
|
|
@@ -714,7 +729,7 @@ function pagerHtml(prev, next) {
|
|
|
714
729
|
</nav>`;
|
|
715
730
|
}
|
|
716
731
|
function docsSidebar(nav, activeUrl, config) {
|
|
717
|
-
const base = config.
|
|
732
|
+
const base = config.site.titleHref ?? "/";
|
|
718
733
|
return `<aside class="voxx-docs__nav"><div class="voxx-docs__nav-inner">
|
|
719
734
|
<div class="voxx-docs__nav-header">
|
|
720
735
|
<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 +949,8 @@ async function build(argv) {
|
|
|
934
949
|
});
|
|
935
950
|
const { config } = result;
|
|
936
951
|
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.`);
|
|
952
|
+
const servesRoot = config.collections.some((col) => stripLead(col.basePath) === "");
|
|
953
|
+
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
954
|
const type = config.content.type;
|
|
938
955
|
const noun = type === "changelog" ? "release" : type === "docs" ? "page" : "post";
|
|
939
956
|
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 @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.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 CORE_NEXT_IMPORT = \"@prudentbird/voxx-core/next\";\n\nconst MINIMAL_NEXT_CONFIG = `import type { NextConfig } from \"next\";\nimport { withVoxx } from \"${CORE_NEXT_IMPORT}\";\n\nconst nextConfig: NextConfig = {};\n\nexport default withVoxx(nextConfig);\n`;\n\ntype ConfigResult =\n | { kind: \"wrapped\" | \"created\" | \"already\"; file: string }\n | { kind: \"manual\" | \"unsupported\" };\n\n/**\n * Wraps the default export of an existing next.config with `withVoxx`, adding\n * the matching import. Returns `null` when no recognizable export is found.\n */\nfunction wrapNextConfig(source: string): string | null {\n const esm = source.lastIndexOf(\"export default \");\n if (esm !== -1) {\n const before = source.slice(0, esm);\n const expr = source\n .slice(esm + \"export default \".length)\n .replace(/;?\\s*$/, \"\");\n return `import { withVoxx } from \"${CORE_NEXT_IMPORT}\";\\n${before}export default withVoxx(${expr});\\n`;\n }\n const cjs = /module\\.exports\\s*=\\s*/.exec(source);\n if (cjs) {\n const start = cjs.index + cjs[0].length;\n const before = source.slice(0, start);\n const expr = source.slice(start).replace(/;?\\s*$/, \"\");\n return `const { withVoxx } = require(\"${CORE_NEXT_IMPORT}\");\\n${before}withVoxx(${expr});\\n`;\n }\n return null;\n}\n\nasync function configureNextConfig(\n cwd: string,\n pkg: Pkg,\n): Promise<ConfigResult> {\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 (/\\bwithVoxx\\b/.test(source)) return { kind: \"already\", file };\n\n const wrapped = wrapNextConfig(source);\n if (wrapped === null) return { kind: \"manual\" };\n await writeFile(join(cwd, file), wrapped);\n return { kind: \"wrapped\", 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: ConfigResult | 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 configureNextConfig(cwd, pkg);\n if (cache.kind === \"wrapped\" || cache.kind === \"created\") {\n results.push([`${cache.file} (wrapped with withVoxx)`, \"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++}. Wrap your config — ${c.cyan(\"export default withVoxx(nextConfig)\")} from ${c.cyan(CORE_NEXT_IMPORT)}.`,\n );\n } else if (cache?.kind === \"unsupported\") {\n log.info(\n ` ${step++}. Upgrade to Next 16+, then wrap your config with ${c.cyan(\"withVoxx\")} from ${c.cyan(CORE_NEXT_IMPORT)}.`,\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(`(next.config already wrapped with withVoxx 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.0
|
|
3
|
+
"version": "1.2.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.2.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^25.9.3",
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"tsdown": "^0.22.2",
|
|
52
52
|
"typescript": "^6.0.3",
|
|
53
53
|
"vitest": "^4.1.8",
|
|
54
|
-
"@voxx/
|
|
55
|
-
"@voxx/
|
|
54
|
+
"@voxx/eslint-config": "0.0.1",
|
|
55
|
+
"@voxx/typescript-config": "0.0.1"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsdown",
|
|
@@ -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>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import "server-only";
|
|
2
|
+
import { cacheLife } from "next/cache";
|
|
2
3
|
import {
|
|
3
4
|
findPost,
|
|
4
5
|
getPosts as coreGetPosts,
|
|
@@ -10,6 +11,7 @@ import { CONTENT_VERSION } from "./content-version";
|
|
|
10
11
|
|
|
11
12
|
async function getPostsCached(version: number): Promise<Post[]> {
|
|
12
13
|
"use cache";
|
|
14
|
+
cacheLife("max");
|
|
13
15
|
void version;
|
|
14
16
|
return coreGetPosts({{COLLECTION_ARG}});
|
|
15
17
|
}
|
|
@@ -20,6 +22,7 @@ export async function getPosts(): Promise<Post[]> {
|
|
|
20
22
|
|
|
21
23
|
async function getConfigCached(version: number): Promise<VoxxConfig> {
|
|
22
24
|
"use cache";
|
|
25
|
+
cacheLife("max");
|
|
23
26
|
void version;
|
|
24
27
|
return coreLoadConfig();
|
|
25
28
|
}
|