kitfly 0.1.2 → 0.2.1
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/CHANGELOG.md +46 -0
- package/README.md +63 -16
- package/VERSION +1 -1
- package/dist/_raw/content/deployment/preflight.md +134 -0
- package/dist/_raw/content/deployment/recipes/aws-s3.md +128 -0
- package/dist/_raw/content/deployment/recipes/cloudflare-pages.md +73 -0
- package/dist/_raw/content/deployment/recipes/cloudflare-r2.md +156 -0
- package/dist/_raw/content/deployment/recipes/fly-io.md +57 -0
- package/dist/_raw/content/deployment/recipes/github-pages.md +112 -0
- package/dist/_raw/content/deployment/recipes/netlify.md +99 -0
- package/dist/_raw/content/deployment/recipes/vercel.md +88 -0
- package/dist/_raw/content/deployment/secrets-and-env-vars.md +75 -0
- package/dist/_raw/content/deployment.md +128 -0
- package/dist/_raw/content/guide/approaches.md +182 -0
- package/dist/_raw/content/guide/features.md +121 -0
- package/dist/_raw/content/guide/getting-started.md +112 -0
- package/dist/_raw/content/guide/kitfly-overview.md +209 -0
- package/dist/_raw/content/reference/configuration.md +259 -0
- package/dist/_raw/content/reference/design-catalog.md +167 -0
- package/dist/_raw/content/reference/environment-variables.md +66 -0
- package/dist/_raw/content/reference/glossary.md +92 -0
- package/dist/_raw/content/reference/key-concepts.md +118 -0
- package/dist/_raw/content/reference/plugins.md +220 -0
- package/dist/_raw/content/reference/slides-authoring-guidelines.md +129 -0
- package/dist/_raw/content/reference/structure.md +166 -0
- package/dist/_raw/content/reference.md +20 -0
- package/dist/_raw/content/templates/crucible.md +192 -0
- package/dist/_raw/content/templates/handbook.md +83 -0
- package/dist/_raw/content/templates/minimal.md +138 -0
- package/dist/_raw/content/templates/overview.md +187 -0
- package/dist/_raw/content/templates/pipeline.md +151 -0
- package/dist/_raw/content/templates/productbook.md +187 -0
- package/dist/_raw/content/templates/runbook.md +193 -0
- package/dist/_raw/content/templates/servicebook.md +163 -0
- package/dist/_raw/docs/decisions/ADR-0001-minimalist-site-code.md +118 -0
- package/dist/_raw/docs/decisions/ADR-0002-ai-accessibility.md +153 -0
- package/dist/_raw/docs/decisions/ADR-0003-single-file-bundle.md +93 -0
- package/dist/_raw/docs/decisions/ADR-0004-bun-runtime.md +98 -0
- package/dist/_raw/docs/decisions/ADR-0005-plugin-contract-and-distribution.md +110 -0
- package/dist/_raw/docs/decisions/DDR-0001-viewport-locked-layout.md +111 -0
- package/dist/_raw/docs/decisions/DDR-0002-theme-system.md +131 -0
- package/dist/_raw/docs/decisions/DDR-0003-bounded-logo-slot.md +106 -0
- package/dist/_raw/docs/decisions/DDR-0004-slides-rendering-model.md +113 -0
- package/dist/_raw/docs/decisions/DDR-0005-deterministic-layout-boundary.md +107 -0
- package/dist/_raw/docs/userguide/cli/build.md +85 -0
- package/dist/_raw/docs/userguide/cli/bundle.md +81 -0
- package/dist/_raw/docs/userguide/cli/dev.md +92 -0
- package/dist/_raw/docs/userguide/cli/init.md +116 -0
- package/dist/_raw/docs/userguide/cli/servers.md +69 -0
- package/dist/_raw/docs/userguide/cli/stop.md +76 -0
- package/dist/_raw/docs/userguide/cli/update.md +78 -0
- package/dist/_raw/docs/userguide/cli/version.md +65 -0
- package/dist/_raw/docs/userguide/cli.md +34 -0
- package/dist/_raw/docs/userguide/sharing.md +94 -0
- package/dist/_raw/schemas/plugin-schemas-notes.md +71 -0
- package/dist/_raw/schemas.md +42 -0
- package/dist/assets/brand/kitfly-favicon-32.png +0 -0
- package/dist/assets/brand/kitfly-icon-64.png +0 -0
- package/dist/assets/brand/kitfly-logo-128.png +0 -0
- package/dist/assets/brand/kitfly-logo-512.png +0 -0
- package/dist/assets/brand/kitfly-logo.svg +12132 -0
- package/dist/assets/brand/kitfly-neon-128.png +0 -0
- package/dist/assets/brand/kitfly-neon-192.png +0 -0
- package/dist/assets/brand/kitfly-neon-256.png +0 -0
- package/dist/assets/brand/kitfly-neon.png +0 -0
- package/dist/assets/brand/palette.md +75 -0
- package/dist/content/deployment/index.html +11 -0
- package/dist/content/deployment/preflight.html +418 -0
- package/dist/content/deployment/recipes/aws-s3.html +421 -0
- package/dist/content/deployment/recipes/cloudflare-pages.html +372 -0
- package/dist/content/deployment/recipes/cloudflare-r2.html +443 -0
- package/dist/content/deployment/recipes/fly-io.html +356 -0
- package/dist/content/deployment/recipes/github-pages.html +414 -0
- package/dist/content/deployment/recipes/index.html +11 -0
- package/dist/content/deployment/recipes/netlify.html +394 -0
- package/dist/content/deployment/recipes/vercel.html +382 -0
- package/dist/content/deployment/secrets-and-env-vars.html +380 -0
- package/dist/content/deployment.html +426 -0
- package/dist/content/guide/approaches.html +501 -0
- package/dist/content/guide/features.html +436 -0
- package/dist/content/guide/getting-started.html +403 -0
- package/dist/content/guide/index.html +11 -0
- package/dist/content/guide/kitfly-overview.html +544 -0
- package/dist/content/index.html +11 -0
- package/dist/content/reference/configuration.html +580 -0
- package/dist/content/reference/design-catalog.html +449 -0
- package/dist/content/reference/environment-variables.html +367 -0
- package/dist/content/reference/glossary.html +368 -0
- package/dist/content/reference/index.html +11 -0
- package/dist/content/reference/key-concepts.html +399 -0
- package/dist/content/reference/plugins.html +491 -0
- package/dist/content/reference/slides-authoring-guidelines.html +418 -0
- package/dist/content/reference/structure.html +463 -0
- package/dist/content/reference.html +335 -0
- package/dist/content/templates/crucible.html +546 -0
- package/dist/content/templates/handbook.html +405 -0
- package/dist/content/templates/index.html +11 -0
- package/dist/content/templates/minimal.html +447 -0
- package/dist/content/templates/overview.html +558 -0
- package/dist/content/templates/pipeline.html +494 -0
- package/dist/content/templates/productbook.html +540 -0
- package/dist/content/templates/runbook.html +543 -0
- package/dist/content/templates/servicebook.html +523 -0
- package/dist/content-index.json +549 -0
- package/dist/docs/decisions/ADR-0001-minimalist-site-code.html +491 -0
- package/dist/docs/decisions/ADR-0002-ai-accessibility.html +434 -0
- package/dist/docs/decisions/ADR-0003-single-file-bundle.html +412 -0
- package/dist/docs/decisions/ADR-0004-bun-runtime.html +409 -0
- package/dist/docs/decisions/ADR-0005-plugin-contract-and-distribution.html +402 -0
- package/dist/docs/decisions/DDR-0001-viewport-locked-layout.html +459 -0
- package/dist/docs/decisions/DDR-0002-theme-system.html +452 -0
- package/dist/docs/decisions/DDR-0003-bounded-logo-slot.html +423 -0
- package/dist/docs/decisions/DDR-0004-slides-rendering-model.html +399 -0
- package/dist/docs/decisions/DDR-0005-deterministic-layout-boundary.html +422 -0
- package/dist/docs/decisions/index.html +11 -0
- package/dist/docs/userguide/cli/build.html +408 -0
- package/dist/docs/userguide/cli/bundle.html +419 -0
- package/dist/docs/userguide/cli/dev.html +428 -0
- package/dist/docs/userguide/cli/index.html +11 -0
- package/dist/docs/userguide/cli/init.html +436 -0
- package/dist/docs/userguide/cli/servers.html +393 -0
- package/dist/docs/userguide/cli/stop.html +408 -0
- package/dist/docs/userguide/cli/update.html +406 -0
- package/dist/docs/userguide/cli/version.html +406 -0
- package/dist/docs/userguide/cli.html +386 -0
- package/dist/docs/userguide/index.html +11 -0
- package/dist/docs/userguide/sharing.html +465 -0
- package/dist/index.html +387 -0
- package/dist/llms.txt +18 -0
- package/dist/provenance.json +7 -0
- package/dist/schemas/index.html +11 -0
- package/dist/schemas/plugin-registry.schema.html +327 -0
- package/dist/schemas/plugin-schemas-notes.html +364 -0
- package/dist/schemas/plugin.schema.html +327 -0
- package/dist/schemas/plugins.schema.html +327 -0
- package/dist/schemas/v0/common.schema.html +386 -0
- package/dist/schemas/v0/index.html +11 -0
- package/dist/schemas/v0/plugin-registry.schema.html +547 -0
- package/dist/schemas/v0/plugin.schema.html +497 -0
- package/dist/schemas/v0/plugins.schema.html +406 -0
- package/dist/schemas/v0/site.schema.html +541 -0
- package/dist/schemas/v0/theme.schema.html +615 -0
- package/dist/schemas.html +351 -0
- package/dist/styles.css +1262 -0
- package/package.json +4 -2
- package/plugins-dist/callouts.css +32 -0
- package/plugins-dist/callouts.js +46 -0
- package/plugins-dist/slides-visuals.css +390 -0
- package/plugins-dist/slides-visuals.js +689 -0
- package/registry/plugins.yaml +35 -0
- package/schemas/README.md +10 -0
- package/schemas/plugin-registry.schema.json +5 -0
- package/schemas/plugin-schemas-notes.md +71 -0
- package/schemas/plugin.schema.json +5 -0
- package/schemas/plugins.schema.json +5 -0
- package/schemas/v0/common.schema.json +64 -0
- package/schemas/v0/plugin-registry.schema.json +225 -0
- package/schemas/v0/plugin.schema.json +175 -0
- package/schemas/v0/plugins.schema.json +84 -0
- package/schemas/v0/site.schema.json +56 -9
- package/schemas/v0/theme.schema.json +105 -22
- package/scripts/build.ts +158 -3
- package/scripts/bundle.ts +261 -95
- package/scripts/dev.ts +301 -11
- package/src/__tests__/build.test.ts +220 -1
- package/src/__tests__/bundle.test.ts +31 -0
- package/src/__tests__/cli.test.ts +14 -3
- package/src/__tests__/dev-plugin-errors.test.ts +20 -0
- package/src/__tests__/fixtures/fences/slides-visuals/invalid/bad-list-indent.md +5 -0
- package/src/__tests__/fixtures/fences/slides-visuals/invalid/blank-line.md +5 -0
- package/src/__tests__/fixtures/fences/slides-visuals/invalid/compare-object-items.md +9 -0
- package/src/__tests__/fixtures/fences/slides-visuals/invalid/flow-branching-no-source.md +5 -0
- package/src/__tests__/fixtures/fences/slides-visuals/invalid/flow-converging-no-target.md +6 -0
- package/src/__tests__/fixtures/fences/slides-visuals/invalid/indented-fence.md +4 -0
- package/src/__tests__/fixtures/fences/slides-visuals/invalid/staircase-empty-steps.md +3 -0
- package/src/__tests__/fixtures/fences/slides-visuals/invalid/stat-grid-missing-fields.md +5 -0
- package/src/__tests__/fixtures/fences/slides-visuals/invalid/timeline-horizontal-no-events.md +2 -0
- package/src/__tests__/fixtures/fences/slides-visuals/invalid/unknown-type.md +3 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/compare.md +10 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/comparison-table.md +14 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-branching-no-split.md +7 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-branching.md +8 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-converging-no-merge.md +7 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-converging.md +8 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/funnel.md +7 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/kpi.md +5 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/layer-cake.md +6 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/pyramid.md +6 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/quadrant-grid.md +8 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/scorecard.md +13 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/staircase-down.md +7 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/staircase.md +8 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/stat-grid.md +8 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/timeline-horizontal.md +9 -0
- package/src/__tests__/fixtures/fences/slides-visuals/valid/timeline-vertical.md +10 -0
- package/src/__tests__/init.test.ts +35 -0
- package/src/__tests__/plugin-loader.test.ts +221 -0
- package/src/__tests__/shared.test.ts +451 -0
- package/src/__tests__/slides-visuals-fence-contract.test.ts +28 -0
- package/src/__tests__/slides-visuals-runtime-regressions.bun.test.ts +147 -0
- package/src/__tests__/styles.test.ts +35 -0
- package/src/cli.ts +9 -4
- package/src/plugin-loader.ts +245 -0
- package/src/shared.ts +650 -7
- package/src/site/styles.css +331 -0
- package/src/site/template.html +66 -5
- package/src/templates/deck.ts +186 -0
- package/src/templates/driver.ts +11 -1
- package/src/templates/minimal.ts +1 -0
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Productbook Template - Kitfly Docs</title>
|
|
7
|
+
<link rel="icon" type="image/png" sizes="32x32" href="../../assets/brand/kitfly-favicon-32.png">
|
|
8
|
+
<link rel="icon" type="image/png" sizes="64x64" href="../../assets/brand/kitfly-neon-256.png">
|
|
9
|
+
<link rel="stylesheet" href="../../styles.css">
|
|
10
|
+
<style id="kitfly-theme">
|
|
11
|
+
:root { --color-bg: #ffffff;
|
|
12
|
+
--color-bg-sidebar: #f5f7f8;
|
|
13
|
+
--color-text: #374151;
|
|
14
|
+
--color-text-muted: #6b7280;
|
|
15
|
+
--color-border: #e5e7eb;
|
|
16
|
+
--color-link: #007182;
|
|
17
|
+
--color-link-hover: #0a6172;
|
|
18
|
+
--color-accent: #152F46;
|
|
19
|
+
--color-code-bg: #f5f7f8;
|
|
20
|
+
--color-logo: #152F46;
|
|
21
|
+
--sidebar-width: 280px;
|
|
22
|
+
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
23
|
+
--font-headings: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
24
|
+
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; }
|
|
25
|
+
html { font-size: 16px; }
|
|
26
|
+
@media (prefers-color-scheme: dark) {
|
|
27
|
+
:root:not([data-theme="light"]) { --color-bg: #0d1117;
|
|
28
|
+
--color-bg-sidebar: #152F46;
|
|
29
|
+
--color-text: #e5e7eb;
|
|
30
|
+
--color-text-muted: #9ca3af;
|
|
31
|
+
--color-border: #374151;
|
|
32
|
+
--color-link: #709EA6;
|
|
33
|
+
--color-link-hover: #8fb5bc;
|
|
34
|
+
--color-accent: #f9fafb;
|
|
35
|
+
--color-code-bg: #152F46;
|
|
36
|
+
--color-logo: #f9fafb; }
|
|
37
|
+
}
|
|
38
|
+
[data-theme="dark"] { --color-bg: #0d1117;
|
|
39
|
+
--color-bg-sidebar: #152F46;
|
|
40
|
+
--color-text: #e5e7eb;
|
|
41
|
+
--color-text-muted: #9ca3af;
|
|
42
|
+
--color-border: #374151;
|
|
43
|
+
--color-link: #709EA6;
|
|
44
|
+
--color-link-hover: #8fb5bc;
|
|
45
|
+
--color-accent: #f9fafb;
|
|
46
|
+
--color-code-bg: #152F46;
|
|
47
|
+
--color-logo: #f9fafb; }
|
|
48
|
+
[data-theme="light"] { --color-bg: #ffffff;
|
|
49
|
+
--color-bg-sidebar: #f5f7f8;
|
|
50
|
+
--color-text: #374151;
|
|
51
|
+
--color-text-muted: #6b7280;
|
|
52
|
+
--color-border: #e5e7eb;
|
|
53
|
+
--color-link: #007182;
|
|
54
|
+
--color-link-hover: #0a6172;
|
|
55
|
+
--color-accent: #152F46;
|
|
56
|
+
--color-code-bg: #f5f7f8;
|
|
57
|
+
--color-logo: #152F46;
|
|
58
|
+
--sidebar-width: 280px;
|
|
59
|
+
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
60
|
+
--font-headings: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
61
|
+
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; }
|
|
62
|
+
</style>
|
|
63
|
+
<!-- Syntax highlighting - Prism.js -->
|
|
64
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism.min.css" id="prism-light">
|
|
65
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism-okaidia.min.css" id="prism-dark" disabled>
|
|
66
|
+
|
|
67
|
+
<script>
|
|
68
|
+
// Apply saved theme immediately to prevent flash
|
|
69
|
+
(function() {
|
|
70
|
+
const saved = localStorage.getItem('theme');
|
|
71
|
+
if (saved) {
|
|
72
|
+
document.documentElement.setAttribute('data-theme', saved);
|
|
73
|
+
}
|
|
74
|
+
// Set Prism theme based on saved or system preference
|
|
75
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
76
|
+
const isDark = saved === 'dark' || (!saved && prefersDark);
|
|
77
|
+
if (isDark) {
|
|
78
|
+
document.getElementById('prism-light')?.setAttribute('disabled', '');
|
|
79
|
+
document.getElementById('prism-dark')?.removeAttribute('disabled');
|
|
80
|
+
}
|
|
81
|
+
})();
|
|
82
|
+
</script>
|
|
83
|
+
</head>
|
|
84
|
+
<body class="mode-docs">
|
|
85
|
+
<div class="mobile-header">
|
|
86
|
+
<button class="nav-toggle" onclick="toggleNav()" aria-label="Toggle navigation">
|
|
87
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
88
|
+
<path d="M3 12h18M3 6h18M3 18h18"/>
|
|
89
|
+
</svg>
|
|
90
|
+
</button>
|
|
91
|
+
<a href="../../" class="mobile-logo" title="Home" data-initial="K">
|
|
92
|
+
<img src="../../assets/brand/kitfly-neon-256.png" alt="Kitfly" class="logo-img logo-icon" onerror="this.onerror=null;this.style.display='none';this.parentElement.classList.add('logo-fallback')"/>
|
|
93
|
+
</a>
|
|
94
|
+
<button class="mobile-theme-toggle" onclick="toggleTheme()" title="Toggle theme" aria-label="Toggle theme">
|
|
95
|
+
<svg class="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
96
|
+
<circle cx="12" cy="12" r="5"/>
|
|
97
|
+
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
|
98
|
+
</svg>
|
|
99
|
+
<svg class="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
100
|
+
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
|
101
|
+
</svg>
|
|
102
|
+
</button>
|
|
103
|
+
</div>
|
|
104
|
+
<div class="layout">
|
|
105
|
+
<nav class="sidebar">
|
|
106
|
+
<div class="sidebar-header">
|
|
107
|
+
<div class="logo logo-icon">
|
|
108
|
+
<a href="/" class="logo-icon" data-initial="K">
|
|
109
|
+
<img src="../../assets/brand/kitfly-neon-256.png" alt="Kitfly" class="logo-img" onerror="this.onerror=null;this.style.display='none';this.parentElement.classList.add('logo-fallback')"/>
|
|
110
|
+
</a>
|
|
111
|
+
<span class="logo-text">
|
|
112
|
+
<a href="/" class="brand">Kitfly</a>
|
|
113
|
+
<a href="../../" class="product">Kitfly Docs</a>
|
|
114
|
+
</span>
|
|
115
|
+
</div>
|
|
116
|
+
<div class="header-tools">
|
|
117
|
+
<button class="theme-toggle" onclick="toggleTheme()" title="Toggle theme" aria-label="Toggle theme">
|
|
118
|
+
<svg class="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
119
|
+
<circle cx="12" cy="12" r="5"/>
|
|
120
|
+
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
|
121
|
+
</svg>
|
|
122
|
+
<svg class="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
123
|
+
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
|
124
|
+
</svg>
|
|
125
|
+
</button>
|
|
126
|
+
<div class="sidebar-meta">
|
|
127
|
+
<span class="meta-version">v0.2.1</span>
|
|
128
|
+
<span class="meta-branch">HEAD</span>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
<div class="sidebar-nav">
|
|
133
|
+
<ul><li><a href="../../index.html" class="nav-home">Home</a></li><li><span class="nav-section">Guide</span><ul><li><a href="../../content/guide/approaches.html">approaches</a></li><li><a href="../../content/guide/features.html">features</a></li><li><a href="../../content/guide/getting-started.html">getting-started</a></li><li><a href="../../content/guide/kitfly-overview.html">kitfly-overview</a></li></ul></li><li><span class="nav-section">Templates</span><ul><li><a href="../../content/templates/crucible.html">crucible</a></li><li><a href="../../content/templates/handbook.html">handbook</a></li><li><a href="../../content/templates/minimal.html">minimal</a></li><li><a href="../../content/templates/overview.html">overview</a></li><li><a href="../../content/templates/pipeline.html">pipeline</a></li><li><a href="../../content/templates/productbook.html" class="active">productbook</a></li><li><a href="../../content/templates/runbook.html">runbook</a></li><li><a href="../../content/templates/servicebook.html">servicebook</a></li></ul></li><li><a href="../../content/reference.html" class="nav-section">Reference</a><ul><li><a href="../../content/reference/configuration.html">configuration</a></li><li><a href="../../content/reference/design-catalog.html">design-catalog</a></li><li><a href="../../content/reference/environment-variables.html">environment-variables</a></li><li><a href="../../content/reference/glossary.html">glossary</a></li><li><a href="../../content/reference/key-concepts.html">key-concepts</a></li><li><a href="../../content/reference/plugins.html">plugins</a></li><li><a href="../../content/reference/slides-authoring-guidelines.html">slides-authoring-guidelines</a></li><li><a href="../../content/reference/structure.html">structure</a></li></ul></li><li><a href="../../content/deployment.html" class="nav-section">Deployment</a><ul><li><a href="../../content/deployment/preflight.html">preflight</a></li><li><details><summary class="nav-group">recipes</summary><ul><li><a href="../../content/deployment/recipes/aws-s3.html">aws-s3</a></li><li><a href="../../content/deployment/recipes/cloudflare-pages.html">cloudflare-pages</a></li><li><a href="../../content/deployment/recipes/cloudflare-r2.html">cloudflare-r2</a></li><li><a href="../../content/deployment/recipes/fly-io.html">fly-io</a></li><li><a href="../../content/deployment/recipes/github-pages.html">github-pages</a></li><li><a href="../../content/deployment/recipes/netlify.html">netlify</a></li><li><a href="../../content/deployment/recipes/vercel.html">vercel</a></li></ul></details></li><li><a href="../../content/deployment/secrets-and-env-vars.html">secrets-and-env-vars</a></li></ul></li><li><span class="nav-section">User Guide</span><ul><li><details><summary class="nav-group"><a href="../../docs/userguide/cli.html">cli</a></summary><ul><li><a href="../../docs/userguide/cli/build.html">build</a></li><li><a href="../../docs/userguide/cli/bundle.html">bundle</a></li><li><a href="../../docs/userguide/cli/dev.html">dev</a></li><li><a href="../../docs/userguide/cli/init.html">init</a></li><li><a href="../../docs/userguide/cli/servers.html">servers</a></li><li><a href="../../docs/userguide/cli/stop.html">stop</a></li><li><a href="../../docs/userguide/cli/update.html">update</a></li><li><a href="../../docs/userguide/cli/version.html">version</a></li></ul></details></li><li><a href="../../docs/userguide/sharing.html">sharing</a></li></ul></li><li><span class="nav-section">Decisions</span><ul><li><a href="../../docs/decisions/ADR-0001-minimalist-site-code.html">ADR-0001-minimalist-site-code</a></li><li><a href="../../docs/decisions/ADR-0002-ai-accessibility.html">ADR-0002-ai-accessibility</a></li><li><a href="../../docs/decisions/ADR-0003-single-file-bundle.html">ADR-0003-single-file-bundle</a></li><li><a href="../../docs/decisions/ADR-0004-bun-runtime.html">ADR-0004-bun-runtime</a></li><li><a href="../../docs/decisions/ADR-0005-plugin-contract-and-distribution.html">ADR-0005-plugin-contract-and-distribution</a></li><li><a href="../../docs/decisions/DDR-0001-viewport-locked-layout.html">DDR-0001-viewport-locked-layout</a></li><li><a href="../../docs/decisions/DDR-0002-theme-system.html">DDR-0002-theme-system</a></li><li><a href="../../docs/decisions/DDR-0003-bounded-logo-slot.html">DDR-0003-bounded-logo-slot</a></li><li><a href="../../docs/decisions/DDR-0004-slides-rendering-model.html">DDR-0004-slides-rendering-model</a></li><li><a href="../../docs/decisions/DDR-0005-deterministic-layout-boundary.html">DDR-0005-deterministic-layout-boundary</a></li></ul></li><li><a href="../../schemas.html" class="nav-section">Schemas</a><ul><li><a href="../../schemas/plugin-registry.schema.html">plugin-registry.schema</a></li><li><a href="../../schemas/plugin-schemas-notes.html">plugin-schemas-notes</a></li><li><a href="../../schemas/plugin.schema.html">plugin.schema</a></li><li><a href="../../schemas/plugins.schema.html">plugins.schema</a></li><li><details><summary class="nav-group">v0</summary><ul><li><a href="../../schemas/v0/common.schema.html">common.schema</a></li><li><a href="../../schemas/v0/plugin-registry.schema.html">plugin-registry.schema</a></li><li><a href="../../schemas/v0/plugin.schema.html">plugin.schema</a></li><li><a href="../../schemas/v0/plugins.schema.html">plugins.schema</a></li><li><a href="../../schemas/v0/site.schema.html">site.schema</a></li><li><a href="../../schemas/v0/theme.schema.html">theme.schema</a></li></ul></details></li></ul></li></ul>
|
|
134
|
+
</div>
|
|
135
|
+
</nav>
|
|
136
|
+
<main class="content">
|
|
137
|
+
<article class="prose">
|
|
138
|
+
<nav class="breadcrumbs"><a href="../../content/guide/approaches.html">Content</a><span class="separator">›</span><a href="../../content/templates/crucible.html">Templates</a><span class="separator">›</span><span>productbook</span></nav>
|
|
139
|
+
|
|
140
|
+
<h1 id="productbook-template">Productbook Template</h1>
|
|
141
|
+
<p>The <code>productbook</code> template creates a documentation site that captures both <strong>product definition</strong> and <strong>business domain knowledge</strong>. It extends <code>minimal</code> with six sections designed for greenfield engagements where the product operates in a complex business domain.</p>
|
|
142
|
+
<h2 id="when-to-use">When to Use</h2>
|
|
143
|
+
<ul>
|
|
144
|
+
<li>Greenfield product development in complex business domains</li>
|
|
145
|
+
<li>Client engagements that need to capture domain expertise alongside product specs</li>
|
|
146
|
+
<li>Products with regulatory, industry, or process complexity</li>
|
|
147
|
+
<li>Projects where the team needs a shared reference for "how this business works"</li>
|
|
148
|
+
<li>Any situation where product decisions depend on deep domain understanding</li>
|
|
149
|
+
</ul>
|
|
150
|
+
<h2 id="what-you-get">What You Get</h2>
|
|
151
|
+
<p>Everything from <code>minimal</code>, plus:</p>
|
|
152
|
+
<pre><code>my-productbook/
|
|
153
|
+
├── site.yaml # Configured with 6 sections
|
|
154
|
+
├── index.md # Home page with product status and quick links
|
|
155
|
+
├── CUSTOMIZING.md # How to customize (AI + human friendly)
|
|
156
|
+
├── content/
|
|
157
|
+
│ ├── product/
|
|
158
|
+
│ │ ├── overview.md # Vision, users, capabilities
|
|
159
|
+
│ │ ├── features/
|
|
160
|
+
│ │ │ └── index.md # Feature catalog
|
|
161
|
+
│ │ └── releases/
|
|
162
|
+
│ │ └── index.md # Release log
|
|
163
|
+
│ ├── domain/
|
|
164
|
+
│ │ ├── overview.md # Business domain context
|
|
165
|
+
│ │ ├── processes/
|
|
166
|
+
│ │ │ └── index.md # Business process catalog
|
|
167
|
+
│ │ ├── data-dictionary.md # Terms and definitions
|
|
168
|
+
│ │ └── industry-notes.md # Regulations and standards
|
|
169
|
+
│ ├── planning/
|
|
170
|
+
│ │ ├── roadmap.md # Phases and priorities
|
|
171
|
+
│ │ ├── decisions/
|
|
172
|
+
│ │ │ ├── index.md # Decision log (ADR pattern)
|
|
173
|
+
│ │ │ └── adr-template.md # ADR template
|
|
174
|
+
│ │ ├── specs/
|
|
175
|
+
│ │ │ └── index.md # Specification index
|
|
176
|
+
│ │ └── research/
|
|
177
|
+
│ │ └── index.md # Research index
|
|
178
|
+
│ ├── operations/
|
|
179
|
+
│ │ ├── environments.md # Dev, staging, production
|
|
180
|
+
│ │ └── deployment.md # Deployment procedures
|
|
181
|
+
│ ├── guides/
|
|
182
|
+
│ │ ├── getting-started.md # Onboarding guide
|
|
183
|
+
│ │ └── user-guide.md # End-user documentation
|
|
184
|
+
│ └── reference/
|
|
185
|
+
│ ├── architecture/
|
|
186
|
+
│ │ └── overview.md # System architecture
|
|
187
|
+
│ ├── integrations/
|
|
188
|
+
│ │ └── index.md # Integration catalog
|
|
189
|
+
│ ├── data-models/
|
|
190
|
+
│ │ └── overview.md # Schemas and data flow
|
|
191
|
+
│ ├── contacts/
|
|
192
|
+
│ │ └── directory.md # Team and vendor contacts
|
|
193
|
+
│ └── metrics/
|
|
194
|
+
│ └── overview.md # KPIs and dashboards
|
|
195
|
+
└── ...
|
|
196
|
+
</code></pre>
|
|
197
|
+
<h2 id="sections">Sections</h2>
|
|
198
|
+
<table>
|
|
199
|
+
<thead>
|
|
200
|
+
<tr>
|
|
201
|
+
<th>Section</th>
|
|
202
|
+
<th>Purpose</th>
|
|
203
|
+
<th>Typical Content</th>
|
|
204
|
+
</tr>
|
|
205
|
+
</thead>
|
|
206
|
+
<tbody><tr>
|
|
207
|
+
<td><strong>Product</strong></td>
|
|
208
|
+
<td>What we're building</td>
|
|
209
|
+
<td>Vision, features, releases, acceptance criteria</td>
|
|
210
|
+
</tr>
|
|
211
|
+
<tr>
|
|
212
|
+
<td><strong>Domain</strong></td>
|
|
213
|
+
<td>The business reality</td>
|
|
214
|
+
<td>Processes, terminology, data dictionary, industry context</td>
|
|
215
|
+
</tr>
|
|
216
|
+
<tr>
|
|
217
|
+
<td><strong>Planning</strong></td>
|
|
218
|
+
<td>Why and when</td>
|
|
219
|
+
<td>Roadmap, ADRs, specifications, research</td>
|
|
220
|
+
</tr>
|
|
221
|
+
<tr>
|
|
222
|
+
<td><strong>Operations</strong></td>
|
|
223
|
+
<td>How we run it</td>
|
|
224
|
+
<td>Environments, deployment, configuration</td>
|
|
225
|
+
</tr>
|
|
226
|
+
<tr>
|
|
227
|
+
<td><strong>Guides</strong></td>
|
|
228
|
+
<td>How to use it</td>
|
|
229
|
+
<td>Onboarding, tutorials, user documentation</td>
|
|
230
|
+
</tr>
|
|
231
|
+
<tr>
|
|
232
|
+
<td><strong>Reference</strong></td>
|
|
233
|
+
<td>Look-up material</td>
|
|
234
|
+
<td>Architecture, integrations, data models, contacts, metrics</td>
|
|
235
|
+
</tr>
|
|
236
|
+
</tbody></table>
|
|
237
|
+
<h2 id="the-domain-section">The Domain Section</h2>
|
|
238
|
+
<p>This is what makes productbook different from every other template. It captures the <strong>complex business reality</strong> that the product operates in.</p>
|
|
239
|
+
<p>For a propane delivery company, this might hold:</p>
|
|
240
|
+
<ul>
|
|
241
|
+
<li><strong>Processes</strong>: Tank monitoring workflow, delivery scheduling, seasonal demand forecasting</li>
|
|
242
|
+
<li><strong>Data Dictionary</strong>: What "will-call" vs "automatic" delivery means, ERP entity definitions</li>
|
|
243
|
+
<li><strong>Industry Notes</strong>: DOT regulations for hazmat transport, state-level propane licensing</li>
|
|
244
|
+
</ul>
|
|
245
|
+
<p>For a healthcare platform:</p>
|
|
246
|
+
<ul>
|
|
247
|
+
<li><strong>Processes</strong>: Claims adjudication, prior authorization, formulary management</li>
|
|
248
|
+
<li><strong>Data Dictionary</strong>: CPT codes, NDC numbers, explanation of benefits</li>
|
|
249
|
+
<li><strong>Industry Notes</strong>: HIPAA requirements, CMS guidelines, state insurance mandates</li>
|
|
250
|
+
</ul>
|
|
251
|
+
<p>This section is the "context dump" that every new team member and AI agent needs. It turns tribal knowledge into navigable documentation.</p>
|
|
252
|
+
<h2 id="planning-artifacts">Planning Artifacts</h2>
|
|
253
|
+
<p>The planning section includes built-in support for common planning patterns:</p>
|
|
254
|
+
<p><strong>Decision Records (ADRs)</strong> — each decision documented with:</p>
|
|
255
|
+
<ul>
|
|
256
|
+
<li>Context: What prompted this decision</li>
|
|
257
|
+
<li>Options: What we considered</li>
|
|
258
|
+
<li>Decision: What we chose and why</li>
|
|
259
|
+
<li>Consequences: What follows from this choice</li>
|
|
260
|
+
</ul>
|
|
261
|
+
<p><strong>Specifications</strong> — feature specs with:</p>
|
|
262
|
+
<ul>
|
|
263
|
+
<li>Problem statement</li>
|
|
264
|
+
<li>Proposed solution</li>
|
|
265
|
+
<li>Acceptance criteria</li>
|
|
266
|
+
<li>Status tracking</li>
|
|
267
|
+
</ul>
|
|
268
|
+
<p><strong>Research</strong> — structured research outputs:</p>
|
|
269
|
+
<ul>
|
|
270
|
+
<li>Market analysis</li>
|
|
271
|
+
<li>User research findings</li>
|
|
272
|
+
<li>Technology assessments</li>
|
|
273
|
+
</ul>
|
|
274
|
+
<p>The sidebar organizes these into collapsible groups — decisions, specs, and research each appear as expandable subsections under Planning.</p>
|
|
275
|
+
<h2 id="usage">Usage</h2>
|
|
276
|
+
<pre><code class="language-bash">kitfly init client-docs --template productbook
|
|
277
|
+
kitfly init client-docs --template productbook --brand "Project Atlas"
|
|
278
|
+
|
|
279
|
+
# With AI assistance instrumentation
|
|
280
|
+
kitfly init client-docs --template productbook --standalone --ai-assist
|
|
281
|
+
</code></pre>
|
|
282
|
+
<h2 id="productbook-vs-other-templates">Productbook vs. Other Templates</h2>
|
|
283
|
+
<table>
|
|
284
|
+
<thead>
|
|
285
|
+
<tr>
|
|
286
|
+
<th>Aspect</th>
|
|
287
|
+
<th>Handbook</th>
|
|
288
|
+
<th>Runbook</th>
|
|
289
|
+
<th>Productbook</th>
|
|
290
|
+
</tr>
|
|
291
|
+
</thead>
|
|
292
|
+
<tbody><tr>
|
|
293
|
+
<td><strong>Orientation</strong></td>
|
|
294
|
+
<td>How we work</td>
|
|
295
|
+
<td>How we keep it running</td>
|
|
296
|
+
<td>What we're building and why</td>
|
|
297
|
+
</tr>
|
|
298
|
+
<tr>
|
|
299
|
+
<td><strong>Assumes</strong></td>
|
|
300
|
+
<td>Team exists</td>
|
|
301
|
+
<td>System exists</td>
|
|
302
|
+
<td>Starting from scratch</td>
|
|
303
|
+
</tr>
|
|
304
|
+
<tr>
|
|
305
|
+
<td><strong>Key section</strong></td>
|
|
306
|
+
<td>Guides</td>
|
|
307
|
+
<td>Procedures</td>
|
|
308
|
+
<td>Domain</td>
|
|
309
|
+
</tr>
|
|
310
|
+
<tr>
|
|
311
|
+
<td><strong>Audience</strong></td>
|
|
312
|
+
<td>Team members</td>
|
|
313
|
+
<td>Operators</td>
|
|
314
|
+
<td>Product team + stakeholders</td>
|
|
315
|
+
</tr>
|
|
316
|
+
<tr>
|
|
317
|
+
<td><strong>Tone</strong></td>
|
|
318
|
+
<td>Explanatory</td>
|
|
319
|
+
<td>Imperative</td>
|
|
320
|
+
<td>Analytical</td>
|
|
321
|
+
</tr>
|
|
322
|
+
</tbody></table>
|
|
323
|
+
<h2 id="growing-your-productbook">Growing Your Productbook</h2>
|
|
324
|
+
<p>As the engagement matures, the sections grow naturally:</p>
|
|
325
|
+
<p><strong>Domain deepens first</strong> — business process docs accumulate as the team learns the domain:</p>
|
|
326
|
+
<pre><code>content/domain/processes/
|
|
327
|
+
├── index.md
|
|
328
|
+
├── order-fulfillment.md
|
|
329
|
+
├── returns-processing.md
|
|
330
|
+
├── inventory-reconciliation.md
|
|
331
|
+
└── seasonal-forecasting.md
|
|
332
|
+
</code></pre>
|
|
333
|
+
<p><strong>Product fills in as features ship</strong> — feature pages link to the domain processes they automate:</p>
|
|
334
|
+
<pre><code>content/product/features/
|
|
335
|
+
├── index.md
|
|
336
|
+
├── auto-scheduling.md # References domain/processes/delivery-scheduling
|
|
337
|
+
├── tank-monitoring.md # References domain/processes/tank-monitoring
|
|
338
|
+
└── customer-portal.md
|
|
339
|
+
</code></pre>
|
|
340
|
+
<p><strong>Planning captures decisions over time</strong> — the ADR log becomes a valuable historical record.</p>
|
|
341
|
+
<h2 id="example-use-cases">Example Use Cases</h2>
|
|
342
|
+
<p><strong>Enterprise SaaS for Complex Industry</strong></p>
|
|
343
|
+
<ul>
|
|
344
|
+
<li>Product: Platform features, integrations, user workflows</li>
|
|
345
|
+
<li>Domain: Industry processes, regulatory requirements, competitive context</li>
|
|
346
|
+
<li>Planning: Roadmap, ADRs for technology and vendor choices</li>
|
|
347
|
+
<li>Guides: Customer onboarding, admin guides</li>
|
|
348
|
+
<li>Reference: API architecture, third-party integrations, data models</li>
|
|
349
|
+
</ul>
|
|
350
|
+
<p><strong>Client Engagement with Legacy System Modernization</strong></p>
|
|
351
|
+
<ul>
|
|
352
|
+
<li>Product: New platform capabilities replacing legacy functions</li>
|
|
353
|
+
<li>Domain: Existing business processes, data structures, edge cases the legacy handles</li>
|
|
354
|
+
<li>Planning: Migration specs, cutover decisions, research on replacement options</li>
|
|
355
|
+
<li>Operations: Parallel-run environments, migration deployment procedures</li>
|
|
356
|
+
<li>Reference: Legacy system documentation, data mapping, vendor contacts</li>
|
|
357
|
+
</ul>
|
|
358
|
+
|
|
359
|
+
</article>
|
|
360
|
+
<aside class="toc"><span class="toc-title">On this page</span><ul><li><a href="#when-to-use">When to Use</a></li><li><a href="#what-you-get">What You Get</a></li><li><a href="#sections">Sections</a></li><li><a href="#the-domain-section">The Domain Section</a></li><li><a href="#planning-artifacts">Planning Artifacts</a></li><li><a href="#usage">Usage</a></li><li><a href="#productbook-vs-other-templates">Productbook vs. Other Templates</a></li><li><a href="#growing-your-productbook">Growing Your Productbook</a></li><li><a href="#example-use-cases">Example Use Cases</a></li></ul></aside>
|
|
361
|
+
</main>
|
|
362
|
+
</div>
|
|
363
|
+
|
|
364
|
+
<footer class="site-footer">
|
|
365
|
+
<div class="footer-content">
|
|
366
|
+
<div class="footer-left">
|
|
367
|
+
<span class="footer-version">v0.2.1</span>
|
|
368
|
+
<span class="footer-separator">·</span>
|
|
369
|
+
<span class="footer-commit" title="Commit: 30dfc01">Published 2026-02-15</span>
|
|
370
|
+
</div>
|
|
371
|
+
<div class="footer-center">
|
|
372
|
+
<span class="footer-copyright"><a href="https://3leaps.net" class="footer-link">© 2026 3 Leaps, LLC</a></span>
|
|
373
|
+
<span class="footer-separator">·</span><a href="/" class="footer-link">Kitfly</a>
|
|
374
|
+
</div>
|
|
375
|
+
<div class="footer-right">
|
|
376
|
+
<a href="https://kitfly.dev" class="footer-link">Built with Kitfly</a>
|
|
377
|
+
</div>
|
|
378
|
+
</div>
|
|
379
|
+
</footer>
|
|
380
|
+
<!-- Syntax highlighting - Prism.js -->
|
|
381
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-core.min.js"></script>
|
|
382
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js"></script>
|
|
383
|
+
<!-- Mermaid diagram support -->
|
|
384
|
+
<script type="module">
|
|
385
|
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
|
386
|
+
|
|
387
|
+
function getMermaidTheme() {
|
|
388
|
+
const theme = document.documentElement.getAttribute('data-theme');
|
|
389
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
390
|
+
const isDark = theme === 'dark' || (!theme && prefersDark);
|
|
391
|
+
return isDark ? 'dark' : 'neutral';
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
mermaid.initialize({
|
|
395
|
+
startOnLoad: true,
|
|
396
|
+
theme: getMermaidTheme()
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
// Re-render mermaid diagrams when theme changes
|
|
400
|
+
window.reinitMermaid = async function() {
|
|
401
|
+
mermaid.initialize({ startOnLoad: false, theme: getMermaidTheme() });
|
|
402
|
+
const diagrams = document.querySelectorAll('.mermaid');
|
|
403
|
+
for (const el of diagrams) {
|
|
404
|
+
const code = el.getAttribute('data-mermaid-source');
|
|
405
|
+
if (code) {
|
|
406
|
+
el.innerHTML = code;
|
|
407
|
+
el.removeAttribute('data-processed');
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
await mermaid.run({ nodes: diagrams });
|
|
411
|
+
};
|
|
412
|
+
</script>
|
|
413
|
+
|
|
414
|
+
<script>
|
|
415
|
+
function toggleTheme() {
|
|
416
|
+
const html = document.documentElement;
|
|
417
|
+
const current = html.getAttribute('data-theme');
|
|
418
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
419
|
+
|
|
420
|
+
let next;
|
|
421
|
+
if (current === 'dark') {
|
|
422
|
+
next = 'light';
|
|
423
|
+
} else if (current === 'light') {
|
|
424
|
+
next = 'dark';
|
|
425
|
+
} else {
|
|
426
|
+
// No explicit theme set, toggle from system preference
|
|
427
|
+
next = prefersDark ? 'light' : 'dark';
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
html.setAttribute('data-theme', next);
|
|
431
|
+
localStorage.setItem('theme', next);
|
|
432
|
+
|
|
433
|
+
// Switch Prism theme
|
|
434
|
+
const prismLight = document.getElementById('prism-light');
|
|
435
|
+
const prismDark = document.getElementById('prism-dark');
|
|
436
|
+
if (next === 'dark') {
|
|
437
|
+
prismLight?.setAttribute('disabled', '');
|
|
438
|
+
prismDark?.removeAttribute('disabled');
|
|
439
|
+
} else {
|
|
440
|
+
prismLight?.removeAttribute('disabled');
|
|
441
|
+
prismDark?.setAttribute('disabled', '');
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Re-render mermaid diagrams with new theme
|
|
445
|
+
if (window.reinitMermaid) {
|
|
446
|
+
window.reinitMermaid();
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Slides mode hash routing
|
|
451
|
+
(function initSlidesMode() {
|
|
452
|
+
const shell = document.querySelector('.slides-shell');
|
|
453
|
+
if (!shell) return;
|
|
454
|
+
|
|
455
|
+
const slides = Array.from(document.querySelectorAll('.slide'));
|
|
456
|
+
if (!slides.length) return;
|
|
457
|
+
|
|
458
|
+
const prevBtn = document.querySelector('.slide-prev');
|
|
459
|
+
const nextBtn = document.querySelector('.slide-next');
|
|
460
|
+
const counter = document.querySelector('.slide-counter');
|
|
461
|
+
const progressBar = document.querySelector('.slide-progress-bar');
|
|
462
|
+
const navLinks = Array.from(document.querySelectorAll('.sidebar-nav a[href^="#slide-"]'));
|
|
463
|
+
let current = 0;
|
|
464
|
+
|
|
465
|
+
function setActive(n) {
|
|
466
|
+
current = Math.max(0, Math.min(n, slides.length - 1));
|
|
467
|
+
slides.forEach((slide, idx) => slide.classList.toggle('active', idx === current));
|
|
468
|
+
navLinks.forEach((link) => {
|
|
469
|
+
const active = link.getAttribute('href') === '#' + slides[current].id;
|
|
470
|
+
link.classList.toggle('active', active);
|
|
471
|
+
});
|
|
472
|
+
if (counter) counter.textContent = (current + 1) + ' / ' + slides.length;
|
|
473
|
+
if (progressBar) progressBar.style.width = (((current + 1) / slides.length) * 100) + '%';
|
|
474
|
+
if (prevBtn) prevBtn.disabled = current === 0;
|
|
475
|
+
if (nextBtn) nextBtn.disabled = current === slides.length - 1;
|
|
476
|
+
history.replaceState(null, '', '#' + slides[current].id);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function setFromHash() {
|
|
480
|
+
const hash = window.location.hash || '';
|
|
481
|
+
const idx = slides.findIndex((s) => '#' + s.id === hash);
|
|
482
|
+
if (idx >= 0) setActive(idx);
|
|
483
|
+
else setActive(0);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
prevBtn?.addEventListener('click', () => setActive(current - 1));
|
|
487
|
+
nextBtn?.addEventListener('click', () => setActive(current + 1));
|
|
488
|
+
|
|
489
|
+
document.addEventListener('keydown', (e) => {
|
|
490
|
+
if (e.key === 'ArrowRight' || e.key === ' ') {
|
|
491
|
+
e.preventDefault();
|
|
492
|
+
setActive(current + 1);
|
|
493
|
+
} else if (e.key === 'ArrowLeft') {
|
|
494
|
+
e.preventDefault();
|
|
495
|
+
setActive(current - 1);
|
|
496
|
+
} else if (e.key === 'Home') {
|
|
497
|
+
e.preventDefault();
|
|
498
|
+
setActive(0);
|
|
499
|
+
} else if (e.key === 'End') {
|
|
500
|
+
e.preventDefault();
|
|
501
|
+
setActive(slides.length - 1);
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
window.addEventListener('hashchange', setFromHash);
|
|
506
|
+
setFromHash();
|
|
507
|
+
})();
|
|
508
|
+
|
|
509
|
+
// Copy code button
|
|
510
|
+
document.querySelectorAll('.prose pre code').forEach(block => {
|
|
511
|
+
const button = document.createElement('button');
|
|
512
|
+
button.className = 'copy-button';
|
|
513
|
+
button.textContent = 'Copy';
|
|
514
|
+
button.onclick = async () => {
|
|
515
|
+
await navigator.clipboard.writeText(block.textContent);
|
|
516
|
+
button.textContent = 'Copied!';
|
|
517
|
+
setTimeout(() => button.textContent = 'Copy', 2000);
|
|
518
|
+
};
|
|
519
|
+
block.parentElement.appendChild(button);
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
// Mobile nav toggle
|
|
523
|
+
function toggleNav() {
|
|
524
|
+
document.querySelector('.sidebar').classList.toggle('open');
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Close nav when clicking outside on mobile
|
|
528
|
+
document.addEventListener('click', (e) => {
|
|
529
|
+
const sidebar = document.querySelector('.sidebar');
|
|
530
|
+
const toggle = document.querySelector('.nav-toggle');
|
|
531
|
+
if (sidebar.classList.contains('open') &&
|
|
532
|
+
!sidebar.contains(e.target) &&
|
|
533
|
+
!toggle.contains(e.target)) {
|
|
534
|
+
sidebar.classList.remove('open');
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
</script>
|
|
538
|
+
|
|
539
|
+
</body>
|
|
540
|
+
</html>
|