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,546 @@
|
|
|
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>Crucible 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" class="active">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">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>crucible</span></nav>
|
|
139
|
+
|
|
140
|
+
<h1 id="crucible-template">Crucible Template</h1>
|
|
141
|
+
<p>The <code>crucible</code> template creates a <strong>layer-0 information architecture site</strong> — the single source of truth (SSOT) for an ecosystem's specifications, schemas, configuration, and governance. It extends <code>minimal</code> with six sections and a four-zone layout that separates rendered documentation from machine-consumable artifacts.</p>
|
|
142
|
+
<h2 id="when-to-use">When to Use</h2>
|
|
143
|
+
<ul>
|
|
144
|
+
<li>Establishing the foundational standards for a new ecosystem or platform</li>
|
|
145
|
+
<li>Centralizing specs, schemas, and config that multiple projects depend on</li>
|
|
146
|
+
<li>Governing an organization's technical standards, policies, and decision records</li>
|
|
147
|
+
<li>Creating a reference architecture that AI agents and humans consume together</li>
|
|
148
|
+
<li>Any situation where you need a "layer 0" that everything else builds on</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-crucible/
|
|
153
|
+
├── site.yaml # Configured with 6 sections
|
|
154
|
+
├── index.md # Home page with standards status and zone overview
|
|
155
|
+
├── CUSTOMIZING.md # Four-zone layout guide (AI + human friendly)
|
|
156
|
+
├── content/
|
|
157
|
+
│ ├── specs/
|
|
158
|
+
│ │ ├── overview.md # Standards catalog with status table
|
|
159
|
+
│ │ └── spec-template.md # Specification template (RFC 2119)
|
|
160
|
+
│ ├── schemas/
|
|
161
|
+
│ │ ├── index.md # Schema catalog linking to raw files
|
|
162
|
+
│ │ └── versioning.md # Schema versioning policy
|
|
163
|
+
│ ├── config/
|
|
164
|
+
│ │ ├── overview.md # Config catalog overview
|
|
165
|
+
│ │ ├── roles.md # Role definitions documentation
|
|
166
|
+
│ │ └── prompts.md # Prompt templates documentation
|
|
167
|
+
│ ├── policies/
|
|
168
|
+
│ │ ├── security-model.md # Security baseline
|
|
169
|
+
│ │ ├── dependency-policy.md # Dependency governance
|
|
170
|
+
│ │ └── change-procedure.md # How changes are approved
|
|
171
|
+
│ ├── guides/
|
|
172
|
+
│ │ ├── getting-started.md # Consuming the crucible
|
|
173
|
+
│ │ └── contributing.md # Adding specs, schemas, config
|
|
174
|
+
│ └── reference/
|
|
175
|
+
│ ├── decisions/
|
|
176
|
+
│ │ ├── index.md # Decision log (ADR pattern)
|
|
177
|
+
│ │ └── adr-template.md # ADR template
|
|
178
|
+
│ ├── changelog/
|
|
179
|
+
│ │ └── index.md # Release log
|
|
180
|
+
│ └── glossary.md # Terminology
|
|
181
|
+
├── internal/
|
|
182
|
+
│ └── ops/
|
|
183
|
+
│ └── README.md # Explains the internal zone
|
|
184
|
+
└── ...
|
|
185
|
+
</code></pre>
|
|
186
|
+
<h2 id="sections">Sections</h2>
|
|
187
|
+
<table>
|
|
188
|
+
<thead>
|
|
189
|
+
<tr>
|
|
190
|
+
<th>Section</th>
|
|
191
|
+
<th>Purpose</th>
|
|
192
|
+
<th>Typical Content</th>
|
|
193
|
+
</tr>
|
|
194
|
+
</thead>
|
|
195
|
+
<tbody><tr>
|
|
196
|
+
<td><strong>Specs</strong></td>
|
|
197
|
+
<td>What the standards are</td>
|
|
198
|
+
<td>Specifications, technical definitions, RFC 2119 requirements</td>
|
|
199
|
+
</tr>
|
|
200
|
+
<tr>
|
|
201
|
+
<td><strong>Schemas</strong></td>
|
|
202
|
+
<td>The contracts</td>
|
|
203
|
+
<td>Schema catalog, versioning policy, field documentation</td>
|
|
204
|
+
</tr>
|
|
205
|
+
<tr>
|
|
206
|
+
<td><strong>Config</strong></td>
|
|
207
|
+
<td>The data</td>
|
|
208
|
+
<td>Configuration catalogs, taxonomies, role and prompt definitions</td>
|
|
209
|
+
</tr>
|
|
210
|
+
<tr>
|
|
211
|
+
<td><strong>Policies</strong></td>
|
|
212
|
+
<td>The rules</td>
|
|
213
|
+
<td>Security model, dependency governance, change procedures</td>
|
|
214
|
+
</tr>
|
|
215
|
+
<tr>
|
|
216
|
+
<td><strong>Guides</strong></td>
|
|
217
|
+
<td>How to use it</td>
|
|
218
|
+
<td>Getting started, contributing, integration guides</td>
|
|
219
|
+
</tr>
|
|
220
|
+
<tr>
|
|
221
|
+
<td><strong>Reference</strong></td>
|
|
222
|
+
<td>Look-up material</td>
|
|
223
|
+
<td>Decision records, changelog, glossary</td>
|
|
224
|
+
</tr>
|
|
225
|
+
</tbody></table>
|
|
226
|
+
<h2 id="the-four-zone-model">The Four-Zone Model</h2>
|
|
227
|
+
<p>This is what makes crucible different from every other template. Crucibles serve two audiences simultaneously — <strong>humans reading documentation</strong> and <strong>machines consuming schemas and config</strong>. The four-zone layout makes this explicit:</p>
|
|
228
|
+
<pre><code>my-crucible/
|
|
229
|
+
├── content/ ← RENDERED: kitfly documentation sections
|
|
230
|
+
├── schemas/ ← MACHINE: JSON Schema files (consumed by code)
|
|
231
|
+
├── config/ ← MACHINE: YAML catalogs, roles, prompts
|
|
232
|
+
├── internal/ ← PROJECT: repo ops, project code, automation
|
|
233
|
+
├── src/ ← KITFLY: site engine (standalone only)
|
|
234
|
+
└── scripts/ ← KITFLY: build scripts (standalone only)
|
|
235
|
+
</code></pre>
|
|
236
|
+
<p><strong>Zone rules:</strong></p>
|
|
237
|
+
<ul>
|
|
238
|
+
<li><code>content/</code> documents the artifacts in other zones (e.g., <code>content/schemas/</code> documents <code>schemas/</code>)</li>
|
|
239
|
+
<li><code>schemas/</code> and <code>config/</code> are machine-consumable — other projects <code>$ref</code> or import from these paths</li>
|
|
240
|
+
<li><code>internal/</code> holds repo housekeeping, project code (lang wrappers, code generators), and automation</li>
|
|
241
|
+
<li><code>src/</code> and <code>scripts/</code> are kitfly's territory (standalone mode only)</li>
|
|
242
|
+
</ul>
|
|
243
|
+
<p>For a WASM skill platform, this might look like:</p>
|
|
244
|
+
<ul>
|
|
245
|
+
<li><strong>Machine zone</strong>: <code>schemas/ipc/v0/control.schema.json</code>, <code>config/agentic/roles/devlead.yaml</code></li>
|
|
246
|
+
<li><strong>Content zone</strong>: <code>content/schemas/ipc-protocol.md</code> documenting those schemas</li>
|
|
247
|
+
<li><strong>Internal zone</strong>: <code>internal/src/</code> for language-specific SDK generators</li>
|
|
248
|
+
</ul>
|
|
249
|
+
<h2 id="the-config-section">The Config Section</h2>
|
|
250
|
+
<p>Crucibles define the <strong>agentic catalog</strong> — roles and prompts that AI agents use across the ecosystem:</p>
|
|
251
|
+
<pre><code>config/agentic/
|
|
252
|
+
├── roles/ # WHO — role definitions (scope, mindset, anti-patterns)
|
|
253
|
+
├── prompts/ # HOW — reusable prompt templates for specific tasks
|
|
254
|
+
└── README.md
|
|
255
|
+
</code></pre>
|
|
256
|
+
<p>Roles define identity ("I am a devlead"). Prompts define approach ("Write a spec following this template"). The <code>content/config/</code> section documents these for human consumption.</p>
|
|
257
|
+
<h2 id="usage">Usage</h2>
|
|
258
|
+
<pre><code class="language-bash">kitfly init my-crucible --template crucible
|
|
259
|
+
kitfly init my-crucible --template crucible --brand "Lanyte Standards"
|
|
260
|
+
|
|
261
|
+
# With AI assistance instrumentation
|
|
262
|
+
kitfly init my-crucible --template crucible --standalone --ai-assist
|
|
263
|
+
</code></pre>
|
|
264
|
+
<h2 id="crucible-vs-other-templates">Crucible vs. Other Templates</h2>
|
|
265
|
+
<table>
|
|
266
|
+
<thead>
|
|
267
|
+
<tr>
|
|
268
|
+
<th>Aspect</th>
|
|
269
|
+
<th>Handbook</th>
|
|
270
|
+
<th>Productbook</th>
|
|
271
|
+
<th>Crucible</th>
|
|
272
|
+
</tr>
|
|
273
|
+
</thead>
|
|
274
|
+
<tbody><tr>
|
|
275
|
+
<td><strong>Orientation</strong></td>
|
|
276
|
+
<td>How we work</td>
|
|
277
|
+
<td>What we build</td>
|
|
278
|
+
<td>What everything is built on</td>
|
|
279
|
+
</tr>
|
|
280
|
+
<tr>
|
|
281
|
+
<td><strong>Assumes</strong></td>
|
|
282
|
+
<td>Team exists</td>
|
|
283
|
+
<td>Product exists</td>
|
|
284
|
+
<td>Ecosystem starting</td>
|
|
285
|
+
</tr>
|
|
286
|
+
<tr>
|
|
287
|
+
<td><strong>Key section</strong></td>
|
|
288
|
+
<td>Guides</td>
|
|
289
|
+
<td>Domain</td>
|
|
290
|
+
<td>Specs</td>
|
|
291
|
+
</tr>
|
|
292
|
+
<tr>
|
|
293
|
+
<td><strong>Audience</strong></td>
|
|
294
|
+
<td>Team members</td>
|
|
295
|
+
<td>Product team</td>
|
|
296
|
+
<td>All consumers + machines</td>
|
|
297
|
+
</tr>
|
|
298
|
+
<tr>
|
|
299
|
+
<td><strong>Tone</strong></td>
|
|
300
|
+
<td>Explanatory</td>
|
|
301
|
+
<td>Analytical</td>
|
|
302
|
+
<td>Prescriptive (RFC 2119)</td>
|
|
303
|
+
</tr>
|
|
304
|
+
<tr>
|
|
305
|
+
<td><strong>Machine artifacts</strong></td>
|
|
306
|
+
<td>None</td>
|
|
307
|
+
<td>None</td>
|
|
308
|
+
<td>Schemas + config alongside docs</td>
|
|
309
|
+
</tr>
|
|
310
|
+
</tbody></table>
|
|
311
|
+
<h2 id="growing-your-crucible">Growing Your Crucible</h2>
|
|
312
|
+
<p>As the ecosystem matures, the sections grow naturally:</p>
|
|
313
|
+
<p><strong>Specs accumulate as standards are defined</strong> — each standard gets its own page:</p>
|
|
314
|
+
<pre><code>content/specs/
|
|
315
|
+
├── overview.md
|
|
316
|
+
├── spec-template.md
|
|
317
|
+
├── skill-abi-v1.md
|
|
318
|
+
├── ipc-protocol.md
|
|
319
|
+
├── autonomy-model.md
|
|
320
|
+
└── capability-model.md
|
|
321
|
+
</code></pre>
|
|
322
|
+
<p><strong>Schemas grow with the type system</strong> — organized by domain and version:</p>
|
|
323
|
+
<pre><code>schemas/
|
|
324
|
+
├── ipc/v0/
|
|
325
|
+
│ ├── control.schema.json
|
|
326
|
+
│ ├── command.schema.json
|
|
327
|
+
│ └── telemetry.schema.json
|
|
328
|
+
├── skill/v0/
|
|
329
|
+
│ ├── manifest.schema.json
|
|
330
|
+
│ └── capability.schema.json
|
|
331
|
+
└── config/v0/
|
|
332
|
+
└── autonomy-gates.schema.json
|
|
333
|
+
</code></pre>
|
|
334
|
+
<p><strong>Policies solidify through experience</strong> — security model, dependency rules, and change procedures evolve.</p>
|
|
335
|
+
<p><strong>Decisions capture the "why"</strong> — the ADR log becomes the institutional memory.</p>
|
|
336
|
+
<h2 id="example-use-cases">Example Use Cases</h2>
|
|
337
|
+
<p><strong>WASM Skill Platform (Lanyte)</strong></p>
|
|
338
|
+
<ul>
|
|
339
|
+
<li>Specs: Skill ABI, IPC protocol, autonomy model, capability taxonomy</li>
|
|
340
|
+
<li>Schemas: IPC message schemas, skill manifest, assessment pipeline</li>
|
|
341
|
+
<li>Config: Autonomy gates, delegation rules, proxy policies</li>
|
|
342
|
+
<li>Policies: Security model, dependency policy, skill assessment criteria</li>
|
|
343
|
+
<li>Guides: Writing skills, deployment, skill assessment process</li>
|
|
344
|
+
<li>Reference: ADRs for architecture choices, CalVer changelog</li>
|
|
345
|
+
</ul>
|
|
346
|
+
<p><strong>Enterprise Ecosystem (FulmenHQ-style)</strong></p>
|
|
347
|
+
<ul>
|
|
348
|
+
<li>Specs: Coding standards, repository category standards, testing standards</li>
|
|
349
|
+
<li>Schemas: Logging schemas, config schemas, error handling schemas</li>
|
|
350
|
+
<li>Config: Repository taxonomy, fixture catalog, branding ecosystem</li>
|
|
351
|
+
<li>Policies: Stream output policy, dependency governance, publishing standards</li>
|
|
352
|
+
<li>Guides: Bootstrap guide, integration patterns, consuming assets</li>
|
|
353
|
+
<li>Reference: Two-tier ADR system, release notes, glossary</li>
|
|
354
|
+
</ul>
|
|
355
|
+
<p><strong>Open Source Foundation</strong></p>
|
|
356
|
+
<ul>
|
|
357
|
+
<li>Specs: API standards, data format specifications, interop requirements</li>
|
|
358
|
+
<li>Schemas: API schemas, event schemas, config schemas</li>
|
|
359
|
+
<li>Config: Project taxonomy, maintainer roles</li>
|
|
360
|
+
<li>Policies: Contribution policy, security disclosure, licensing</li>
|
|
361
|
+
<li>Guides: Getting started, SDK integration, migration guides</li>
|
|
362
|
+
<li>Reference: Governance decisions, release history, terminology</li>
|
|
363
|
+
</ul>
|
|
364
|
+
|
|
365
|
+
</article>
|
|
366
|
+
<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-four-zone-model">The Four-Zone Model</a></li><li><a href="#the-config-section">The Config Section</a></li><li><a href="#usage">Usage</a></li><li><a href="#crucible-vs-other-templates">Crucible vs. Other Templates</a></li><li><a href="#growing-your-crucible">Growing Your Crucible</a></li><li><a href="#example-use-cases">Example Use Cases</a></li></ul></aside>
|
|
367
|
+
</main>
|
|
368
|
+
</div>
|
|
369
|
+
|
|
370
|
+
<footer class="site-footer">
|
|
371
|
+
<div class="footer-content">
|
|
372
|
+
<div class="footer-left">
|
|
373
|
+
<span class="footer-version">v0.2.1</span>
|
|
374
|
+
<span class="footer-separator">·</span>
|
|
375
|
+
<span class="footer-commit" title="Commit: 30dfc01">Published 2026-02-15</span>
|
|
376
|
+
</div>
|
|
377
|
+
<div class="footer-center">
|
|
378
|
+
<span class="footer-copyright"><a href="https://3leaps.net" class="footer-link">© 2026 3 Leaps, LLC</a></span>
|
|
379
|
+
<span class="footer-separator">·</span><a href="/" class="footer-link">Kitfly</a>
|
|
380
|
+
</div>
|
|
381
|
+
<div class="footer-right">
|
|
382
|
+
<a href="https://kitfly.dev" class="footer-link">Built with Kitfly</a>
|
|
383
|
+
</div>
|
|
384
|
+
</div>
|
|
385
|
+
</footer>
|
|
386
|
+
<!-- Syntax highlighting - Prism.js -->
|
|
387
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-core.min.js"></script>
|
|
388
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js"></script>
|
|
389
|
+
<!-- Mermaid diagram support -->
|
|
390
|
+
<script type="module">
|
|
391
|
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
|
392
|
+
|
|
393
|
+
function getMermaidTheme() {
|
|
394
|
+
const theme = document.documentElement.getAttribute('data-theme');
|
|
395
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
396
|
+
const isDark = theme === 'dark' || (!theme && prefersDark);
|
|
397
|
+
return isDark ? 'dark' : 'neutral';
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
mermaid.initialize({
|
|
401
|
+
startOnLoad: true,
|
|
402
|
+
theme: getMermaidTheme()
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
// Re-render mermaid diagrams when theme changes
|
|
406
|
+
window.reinitMermaid = async function() {
|
|
407
|
+
mermaid.initialize({ startOnLoad: false, theme: getMermaidTheme() });
|
|
408
|
+
const diagrams = document.querySelectorAll('.mermaid');
|
|
409
|
+
for (const el of diagrams) {
|
|
410
|
+
const code = el.getAttribute('data-mermaid-source');
|
|
411
|
+
if (code) {
|
|
412
|
+
el.innerHTML = code;
|
|
413
|
+
el.removeAttribute('data-processed');
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
await mermaid.run({ nodes: diagrams });
|
|
417
|
+
};
|
|
418
|
+
</script>
|
|
419
|
+
|
|
420
|
+
<script>
|
|
421
|
+
function toggleTheme() {
|
|
422
|
+
const html = document.documentElement;
|
|
423
|
+
const current = html.getAttribute('data-theme');
|
|
424
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
425
|
+
|
|
426
|
+
let next;
|
|
427
|
+
if (current === 'dark') {
|
|
428
|
+
next = 'light';
|
|
429
|
+
} else if (current === 'light') {
|
|
430
|
+
next = 'dark';
|
|
431
|
+
} else {
|
|
432
|
+
// No explicit theme set, toggle from system preference
|
|
433
|
+
next = prefersDark ? 'light' : 'dark';
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
html.setAttribute('data-theme', next);
|
|
437
|
+
localStorage.setItem('theme', next);
|
|
438
|
+
|
|
439
|
+
// Switch Prism theme
|
|
440
|
+
const prismLight = document.getElementById('prism-light');
|
|
441
|
+
const prismDark = document.getElementById('prism-dark');
|
|
442
|
+
if (next === 'dark') {
|
|
443
|
+
prismLight?.setAttribute('disabled', '');
|
|
444
|
+
prismDark?.removeAttribute('disabled');
|
|
445
|
+
} else {
|
|
446
|
+
prismLight?.removeAttribute('disabled');
|
|
447
|
+
prismDark?.setAttribute('disabled', '');
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// Re-render mermaid diagrams with new theme
|
|
451
|
+
if (window.reinitMermaid) {
|
|
452
|
+
window.reinitMermaid();
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Slides mode hash routing
|
|
457
|
+
(function initSlidesMode() {
|
|
458
|
+
const shell = document.querySelector('.slides-shell');
|
|
459
|
+
if (!shell) return;
|
|
460
|
+
|
|
461
|
+
const slides = Array.from(document.querySelectorAll('.slide'));
|
|
462
|
+
if (!slides.length) return;
|
|
463
|
+
|
|
464
|
+
const prevBtn = document.querySelector('.slide-prev');
|
|
465
|
+
const nextBtn = document.querySelector('.slide-next');
|
|
466
|
+
const counter = document.querySelector('.slide-counter');
|
|
467
|
+
const progressBar = document.querySelector('.slide-progress-bar');
|
|
468
|
+
const navLinks = Array.from(document.querySelectorAll('.sidebar-nav a[href^="#slide-"]'));
|
|
469
|
+
let current = 0;
|
|
470
|
+
|
|
471
|
+
function setActive(n) {
|
|
472
|
+
current = Math.max(0, Math.min(n, slides.length - 1));
|
|
473
|
+
slides.forEach((slide, idx) => slide.classList.toggle('active', idx === current));
|
|
474
|
+
navLinks.forEach((link) => {
|
|
475
|
+
const active = link.getAttribute('href') === '#' + slides[current].id;
|
|
476
|
+
link.classList.toggle('active', active);
|
|
477
|
+
});
|
|
478
|
+
if (counter) counter.textContent = (current + 1) + ' / ' + slides.length;
|
|
479
|
+
if (progressBar) progressBar.style.width = (((current + 1) / slides.length) * 100) + '%';
|
|
480
|
+
if (prevBtn) prevBtn.disabled = current === 0;
|
|
481
|
+
if (nextBtn) nextBtn.disabled = current === slides.length - 1;
|
|
482
|
+
history.replaceState(null, '', '#' + slides[current].id);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function setFromHash() {
|
|
486
|
+
const hash = window.location.hash || '';
|
|
487
|
+
const idx = slides.findIndex((s) => '#' + s.id === hash);
|
|
488
|
+
if (idx >= 0) setActive(idx);
|
|
489
|
+
else setActive(0);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
prevBtn?.addEventListener('click', () => setActive(current - 1));
|
|
493
|
+
nextBtn?.addEventListener('click', () => setActive(current + 1));
|
|
494
|
+
|
|
495
|
+
document.addEventListener('keydown', (e) => {
|
|
496
|
+
if (e.key === 'ArrowRight' || e.key === ' ') {
|
|
497
|
+
e.preventDefault();
|
|
498
|
+
setActive(current + 1);
|
|
499
|
+
} else if (e.key === 'ArrowLeft') {
|
|
500
|
+
e.preventDefault();
|
|
501
|
+
setActive(current - 1);
|
|
502
|
+
} else if (e.key === 'Home') {
|
|
503
|
+
e.preventDefault();
|
|
504
|
+
setActive(0);
|
|
505
|
+
} else if (e.key === 'End') {
|
|
506
|
+
e.preventDefault();
|
|
507
|
+
setActive(slides.length - 1);
|
|
508
|
+
}
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
window.addEventListener('hashchange', setFromHash);
|
|
512
|
+
setFromHash();
|
|
513
|
+
})();
|
|
514
|
+
|
|
515
|
+
// Copy code button
|
|
516
|
+
document.querySelectorAll('.prose pre code').forEach(block => {
|
|
517
|
+
const button = document.createElement('button');
|
|
518
|
+
button.className = 'copy-button';
|
|
519
|
+
button.textContent = 'Copy';
|
|
520
|
+
button.onclick = async () => {
|
|
521
|
+
await navigator.clipboard.writeText(block.textContent);
|
|
522
|
+
button.textContent = 'Copied!';
|
|
523
|
+
setTimeout(() => button.textContent = 'Copy', 2000);
|
|
524
|
+
};
|
|
525
|
+
block.parentElement.appendChild(button);
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
// Mobile nav toggle
|
|
529
|
+
function toggleNav() {
|
|
530
|
+
document.querySelector('.sidebar').classList.toggle('open');
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Close nav when clicking outside on mobile
|
|
534
|
+
document.addEventListener('click', (e) => {
|
|
535
|
+
const sidebar = document.querySelector('.sidebar');
|
|
536
|
+
const toggle = document.querySelector('.nav-toggle');
|
|
537
|
+
if (sidebar.classList.contains('open') &&
|
|
538
|
+
!sidebar.contains(e.target) &&
|
|
539
|
+
!toggle.contains(e.target)) {
|
|
540
|
+
sidebar.classList.remove('open');
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
</script>
|
|
544
|
+
|
|
545
|
+
</body>
|
|
546
|
+
</html>
|