mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-18 00:56:30 +03:00
Generate /skills index + 21 auto-rendered skill detail pages
Ships the first new sub-page section. Every user-invocable skill now has
its own page at /skills/{id}, with the canonical SKILL.md body rendered
via marked. The index at /skills lists all 21 skills grouped by category.
Editorial wrappers are opt-in: if content/site/skills/{id}.md exists, it
renders above the canonical body (with a "The skill itself" divider).
All 21 pages currently ship with the auto-rendered body only; hand-written
wrappers land in the next few commits.
- scripts/lib/sub-pages-data.js: builds the data model. Reuses
readSourceFiles() from lib/utils.js for skill content; parses the
ANTIPATTERNS array out of src/detect-antipatterns.mjs; reads optional
editorial wrappers from content/site/skills/*.md; validates that every
user-invocable skill has a category entry (build fails loudly if not).
- scripts/build-sub-pages.js: orchestrator. Writes generated HTML into
public/skills/*.html (gitignored). Called from both scripts/build.js
(before buildStaticSite) and server/index.js (at module load) so dev
and prod share the same generation code path.
- scripts/lib/render-page.js: new assetDepth parameter so generated
pages one level deep under public/ use relative paths (../favicon.svg,
../css/sub-pages.css) that Bun's HTML loader can resolve on disk.
- scripts/build.js: pass generated files into Bun.build entrypoints;
post-process to flatten build/public/* → build/* (Bun preserves the
public/ prefix when entrypoints span multiple depths).
- server/index.js: generateSubPages() runs at module load; new routes
/skills, /skills/:id, /anti-patterns, /tutorials, /tutorials/:slug
serve the pre-generated files via Bun.file().
- public/css/sub-pages.css: adds sub-page layout shell, skills index
grouped-list styling, skill detail header/meta chips/divider, collapsed
<details> reference sections, and a .prose block for rendered markdown
with editorial typography, code blocks, and inline code.
Verified: bun run build produces 26 HTML files (4 hand-authored + 22
generated), all flat under build/. Dev server returns 200 on /skills,
/skills/polish, /skills/impeccable, /skills/critique. Tests pass.
This commit is contained in:
@@ -55,6 +55,7 @@ export function applyActiveNav(headerHtml, activeNav) {
|
||||
* @param {string} [opts.canonicalPath] - relative URL path for <link rel="canonical">
|
||||
* @param {string} [opts.extraHead] - raw HTML to inject into <head>
|
||||
* @param {string} [opts.bodyClass] - optional class on <body>
|
||||
* @param {number} [opts.assetDepth] - how many `..` to prepend for Bun's HTML loader to resolve on-disk paths. 1 = page is one dir deep under public/ (e.g. public/skills/polish.html). Defaults to 1.
|
||||
* @returns {string} full HTML document
|
||||
*/
|
||||
export function renderPage({
|
||||
@@ -65,6 +66,7 @@ export function renderPage({
|
||||
canonicalPath,
|
||||
extraHead = '',
|
||||
bodyClass = 'sub-page',
|
||||
assetDepth = 1,
|
||||
}) {
|
||||
const header = applyActiveNav(readHeaderPartial(), activeNav);
|
||||
const safeTitle = escapeHtml(title);
|
||||
@@ -73,6 +75,11 @@ export function renderPage({
|
||||
? `<link rel="canonical" href="https://impeccable.style${canonicalPath}">`
|
||||
: '';
|
||||
|
||||
// Relative prefix for on-disk resolution by Bun's HTML loader.
|
||||
// Bun rewrites these to hashed absolute URLs at build time, so runtime
|
||||
// serving works regardless of the request path.
|
||||
const rel = assetDepth > 0 ? '../'.repeat(assetDepth) : './';
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -82,11 +89,11 @@ export function renderPage({
|
||||
<meta name="description" content="${safeDesc}">
|
||||
<meta name="theme-color" content="#fafafa">
|
||||
${canonical}
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||
<link rel="icon" type="image/svg+xml" href="${rel}favicon.svg">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,600;1,400&family=Instrument+Sans:wght@400;500;600;700&family=Space+Grotesk:wght@400;500;600&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/css/sub-pages.css">
|
||||
<link rel="stylesheet" href="${rel}css/sub-pages.css">
|
||||
${extraHead}
|
||||
</head>
|
||||
<body class="${bodyClass}">
|
||||
|
||||
Reference in New Issue
Block a user