kitfly 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -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/structure.md +166 -0
- package/dist/_raw/content/reference.md +19 -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/structure.html +463 -0
- package/dist/content/reference.html +334 -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 +540 -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 +224 -0
- package/plugins-dist/slides-visuals.js +598 -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 +155 -3
- package/scripts/bundle.ts +258 -95
- package/scripts/dev.ts +203 -1
- package/src/__tests__/build.test.ts +158 -1
- package/src/__tests__/bundle.test.ts +31 -0
- package/src/__tests__/cli.test.ts +14 -3
- 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/indented-fence.md +4 -0
- package/src/__tests__/fixtures/fences/slides-visuals/invalid/stat-grid-missing-fields.md +5 -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/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/stat-grid.md +8 -0
- package/src/__tests__/init.test.ts +35 -0
- package/src/__tests__/plugin-loader.test.ts +221 -0
- package/src/__tests__/shared.test.ts +428 -0
- package/src/__tests__/slides-visuals-fence-contract.test.ts +28 -0
- package/src/__tests__/slides-visuals-runtime-regressions.bun.test.ts +114 -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 +614 -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,501 @@
|
|
|
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>Approaches - 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.0</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" class="active">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">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/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/guide/approaches.html">Guide</a><span class="separator">›</span><span>approaches</span></nav>
|
|
139
|
+
<div class="page-meta">Last updated: 2026-02-03</div>
|
|
140
|
+
<h1 id="three-ways-to-use-kitfly">Three Ways to Use Kitfly</h1>
|
|
141
|
+
<p>Kitfly adapts to how you work. Choose the approach that fits your situation.</p>
|
|
142
|
+
<h2 id="1-clone-customize">1. Clone & Customize</h2>
|
|
143
|
+
<p><strong>What you get:</strong> The Kitfly engine repo (renderer, template HTML/CSS, example content).</p>
|
|
144
|
+
<pre><code class="language-bash">git clone https://github.com/3leaps/kitfly my-docs
|
|
145
|
+
cd my-docs
|
|
146
|
+
bun install
|
|
147
|
+
bun run dev
|
|
148
|
+
</code></pre>
|
|
149
|
+
<p><strong>Directory structure:</strong></p>
|
|
150
|
+
<pre><code>my-docs/
|
|
151
|
+
├── content/ # Replace this with your docs
|
|
152
|
+
│ ├── index.md
|
|
153
|
+
│ └── guide/
|
|
154
|
+
├── src/ # Rendering code (keep this)
|
|
155
|
+
├── scripts/ # Build scripts (keep this)
|
|
156
|
+
├── site.yaml # Edit to customize
|
|
157
|
+
├── package.json # Dependencies
|
|
158
|
+
└── ... # Other template files
|
|
159
|
+
</code></pre>
|
|
160
|
+
<p><strong>When to use:</strong></p>
|
|
161
|
+
<ul>
|
|
162
|
+
<li>You want to understand or modify how kitfly works</li>
|
|
163
|
+
<li>You plan to customize the HTML template or CSS</li>
|
|
164
|
+
<li>You want version control of the tooling alongside your docs</li>
|
|
165
|
+
<li>You're comfortable with a bit of extra files in your repo</li>
|
|
166
|
+
</ul>
|
|
167
|
+
<p>If you're not changing Kitfly itself, prefer <code>kitfly init</code> or pointing Kitfly at a folder.</p>
|
|
168
|
+
<p><strong>Trade-offs:</strong></p>
|
|
169
|
+
<ul>
|
|
170
|
+
<li>More files to manage</li>
|
|
171
|
+
<li>Your docs repo includes rendering code</li>
|
|
172
|
+
<li>Updates require manual merging from upstream</li>
|
|
173
|
+
</ul>
|
|
174
|
+
<h2 id="2-cli-init">2. CLI Init</h2>
|
|
175
|
+
<p><strong>What you get:</strong> A clean workspace with minimal structure.</p>
|
|
176
|
+
<pre><code class="language-bash"># Create new site root
|
|
177
|
+
kitfly init my-handbook
|
|
178
|
+
cd my-handbook
|
|
179
|
+
kitfly dev
|
|
180
|
+
</code></pre>
|
|
181
|
+
<p><strong>Directory structure:</strong></p>
|
|
182
|
+
<pre><code>my-handbook/
|
|
183
|
+
├── content/
|
|
184
|
+
│ ├── index.md
|
|
185
|
+
│ └── guide/
|
|
186
|
+
│ └── getting-started.md
|
|
187
|
+
├── site.yaml
|
|
188
|
+
└── .gitignore
|
|
189
|
+
</code></pre>
|
|
190
|
+
<p><strong>When to use:</strong></p>
|
|
191
|
+
<ul>
|
|
192
|
+
<li>You want a clean start without template clutter</li>
|
|
193
|
+
<li>You prefer your docs separate from tooling</li>
|
|
194
|
+
<li>You're starting a new documentation project</li>
|
|
195
|
+
<li>You want the simplest possible structure</li>
|
|
196
|
+
</ul>
|
|
197
|
+
<p><strong>Trade-offs:</strong></p>
|
|
198
|
+
<ul>
|
|
199
|
+
<li>Requires kitfly installed (binary or via a JS runtime)</li>
|
|
200
|
+
<li>Can't customize the rendering without ejecting</li>
|
|
201
|
+
<li>Depends on kitfly CLI being available</li>
|
|
202
|
+
</ul>
|
|
203
|
+
<h2 id="3-point-at-folder">3. Point at Folder</h2>
|
|
204
|
+
<p><strong>What you get:</strong> Instant rendering of any markdown folder.</p>
|
|
205
|
+
<pre><code class="language-bash"># Preview existing docs
|
|
206
|
+
kitfly dev ./docs
|
|
207
|
+
|
|
208
|
+
# Build to static HTML
|
|
209
|
+
kitfly build ./docs --out ./dist
|
|
210
|
+
|
|
211
|
+
# Custom port
|
|
212
|
+
kitfly dev ./docs --port 4000
|
|
213
|
+
</code></pre>
|
|
214
|
+
<p><strong>Directory structure:</strong> Whatever you already have.</p>
|
|
215
|
+
<pre><code>my-project/
|
|
216
|
+
├── docs/ # kitfly renders this
|
|
217
|
+
│ ├── README.md
|
|
218
|
+
│ ├── api/
|
|
219
|
+
│ └── guides/
|
|
220
|
+
├── src/ # Your project code (ignored)
|
|
221
|
+
└── ...
|
|
222
|
+
</code></pre>
|
|
223
|
+
<p><strong>When to use:</strong></p>
|
|
224
|
+
<ul>
|
|
225
|
+
<li>You have existing markdown you want to render</li>
|
|
226
|
+
<li>You want to preview docs in another repo</li>
|
|
227
|
+
<li>You're experimenting before committing to a structure</li>
|
|
228
|
+
<li>You need a quick way to share markdown as HTML</li>
|
|
229
|
+
</ul>
|
|
230
|
+
<p><strong>Trade-offs:</strong></p>
|
|
231
|
+
<ul>
|
|
232
|
+
<li>No <code>site.yaml</code> means less control (auto-discovery only)</li>
|
|
233
|
+
<li>Need to create <code>site.yaml</code> in the folder for customization</li>
|
|
234
|
+
<li>Requires kitfly installed</li>
|
|
235
|
+
</ul>
|
|
236
|
+
<h2 id="comparison-table">Comparison Table</h2>
|
|
237
|
+
<table>
|
|
238
|
+
<thead>
|
|
239
|
+
<tr>
|
|
240
|
+
<th>Factor</th>
|
|
241
|
+
<th>Clone & Customize</th>
|
|
242
|
+
<th>CLI Init</th>
|
|
243
|
+
<th>Point at Folder</th>
|
|
244
|
+
</tr>
|
|
245
|
+
</thead>
|
|
246
|
+
<tbody><tr>
|
|
247
|
+
<td>Setup time</td>
|
|
248
|
+
<td>~1 min</td>
|
|
249
|
+
<td>~30 sec</td>
|
|
250
|
+
<td>Instant</td>
|
|
251
|
+
</tr>
|
|
252
|
+
<tr>
|
|
253
|
+
<td>Files in repo</td>
|
|
254
|
+
<td>Many</td>
|
|
255
|
+
<td>Few</td>
|
|
256
|
+
<td>None added</td>
|
|
257
|
+
</tr>
|
|
258
|
+
<tr>
|
|
259
|
+
<td>Customization</td>
|
|
260
|
+
<td>Full</td>
|
|
261
|
+
<td>Config only</td>
|
|
262
|
+
<td>Config only</td>
|
|
263
|
+
</tr>
|
|
264
|
+
<tr>
|
|
265
|
+
<td>Requires install</td>
|
|
266
|
+
<td>Bun</td>
|
|
267
|
+
<td>Kitfly CLI</td>
|
|
268
|
+
<td>Kitfly CLI</td>
|
|
269
|
+
</tr>
|
|
270
|
+
<tr>
|
|
271
|
+
<td>Updates</td>
|
|
272
|
+
<td>Manual merge</td>
|
|
273
|
+
<td>CLI upgrade</td>
|
|
274
|
+
<td>CLI upgrade</td>
|
|
275
|
+
</tr>
|
|
276
|
+
<tr>
|
|
277
|
+
<td>Best for</td>
|
|
278
|
+
<td>Power users</td>
|
|
279
|
+
<td>New projects</td>
|
|
280
|
+
<td>Existing docs</td>
|
|
281
|
+
</tr>
|
|
282
|
+
</tbody></table>
|
|
283
|
+
<h2 id="migrating-between-approaches">Migrating Between Approaches</h2>
|
|
284
|
+
<h3 id="from-clone-to-point-at-folder">From Clone to Point-at-Folder</h3>
|
|
285
|
+
<p>If you started with the template but want to separate your docs:</p>
|
|
286
|
+
<ol>
|
|
287
|
+
<li>Copy your <code>content/</code> folder to a new location</li>
|
|
288
|
+
<li>Copy <code>site.yaml</code> alongside it</li>
|
|
289
|
+
<li>Run <code>kitfly dev ./new-location</code></li>
|
|
290
|
+
</ol>
|
|
291
|
+
<h3 id="from-point-at-folder-to-a-dedicated-site-root">From Point-at-Folder to A Dedicated Site Root</h3>
|
|
292
|
+
<p>If you want a clean top-level folder for publishing:</p>
|
|
293
|
+
<ol>
|
|
294
|
+
<li>Run <code>kitfly init my-new-site</code></li>
|
|
295
|
+
<li>Copy your docs into <code>my-new-site/content/</code></li>
|
|
296
|
+
<li>Run <code>kitfly dev my-new-site</code></li>
|
|
297
|
+
</ol>
|
|
298
|
+
<h3 id="from-point-at-folder-to-init">From Point-at-Folder to Init</h3>
|
|
299
|
+
<p>If you want more structure:</p>
|
|
300
|
+
<ol>
|
|
301
|
+
<li>Run <code>kitfly init my-new-docs</code></li>
|
|
302
|
+
<li>Copy your markdown into <code>content/</code></li>
|
|
303
|
+
<li>Configure <code>site.yaml</code></li>
|
|
304
|
+
</ol>
|
|
305
|
+
<h3 id="from-init-to-clone">From Init to Clone</h3>
|
|
306
|
+
<p>If you need to customize the rendering:</p>
|
|
307
|
+
<ol>
|
|
308
|
+
<li>Clone the full template</li>
|
|
309
|
+
<li>Copy your <code>content/</code> folder over</li>
|
|
310
|
+
<li>Preserve your <code>site.yaml</code> customizations</li>
|
|
311
|
+
</ol>
|
|
312
|
+
<h2 id="the-docroot-concept">The docroot Concept</h2>
|
|
313
|
+
<p>Regardless of approach, the <code>docroot</code> setting (in <code>site.yaml</code>) controls what gets rendered:</p>
|
|
314
|
+
<pre><code class="language-yaml">docroot: "content" # Only content/ goes in dist/
|
|
315
|
+
docroot: "docs" # Only docs/ goes in dist/
|
|
316
|
+
docroot: "." # Everything in current dir goes in dist/
|
|
317
|
+
</code></pre>
|
|
318
|
+
<p>This is how kitfly separates your documentation from other files in your repo. The machinery (<code>src/</code>, <code>scripts/</code>, <code>README.md</code>, etc.) never appears in your built site unless you explicitly configure it.</p>
|
|
319
|
+
|
|
320
|
+
</article>
|
|
321
|
+
<aside class="toc"><span class="toc-title">On this page</span><ul><li><a href="#1-clone-customize">1. Clone & Customize</a></li><li><a href="#2-cli-init">2. CLI Init</a></li><li><a href="#3-point-at-folder">3. Point at Folder</a></li><li><a href="#comparison-table">Comparison Table</a></li><li><a href="#migrating-between-approaches">Migrating Between Approaches</a></li><li class="toc-h3"><a href="#from-clone-to-point-at-folder">From Clone to Point-at-Folder</a></li><li class="toc-h3"><a href="#from-point-at-folder-to-a-dedicated-site-root">From Point-at-Folder to A Dedicated Site Root</a></li><li class="toc-h3"><a href="#from-point-at-folder-to-init">From Point-at-Folder to Init</a></li><li class="toc-h3"><a href="#from-init-to-clone">From Init to Clone</a></li><li><a href="#the-docroot-concept">The docroot Concept</a></li></ul></aside>
|
|
322
|
+
</main>
|
|
323
|
+
</div>
|
|
324
|
+
|
|
325
|
+
<footer class="site-footer">
|
|
326
|
+
<div class="footer-content">
|
|
327
|
+
<div class="footer-left">
|
|
328
|
+
<span class="footer-version">v0.2.0</span>
|
|
329
|
+
<span class="footer-separator">·</span>
|
|
330
|
+
<span class="footer-commit" title="Commit: 33ccd68">Published 2026-02-15</span>
|
|
331
|
+
</div>
|
|
332
|
+
<div class="footer-center">
|
|
333
|
+
<span class="footer-copyright"><a href="https://3leaps.net" class="footer-link">© 2026 3 Leaps, LLC</a></span>
|
|
334
|
+
<span class="footer-separator">·</span><a href="/" class="footer-link">Kitfly</a>
|
|
335
|
+
</div>
|
|
336
|
+
<div class="footer-right">
|
|
337
|
+
<a href="https://kitfly.dev" class="footer-link">Built with Kitfly</a>
|
|
338
|
+
</div>
|
|
339
|
+
</div>
|
|
340
|
+
</footer>
|
|
341
|
+
<!-- Syntax highlighting - Prism.js -->
|
|
342
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-core.min.js"></script>
|
|
343
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js"></script>
|
|
344
|
+
<!-- Mermaid diagram support -->
|
|
345
|
+
<script type="module">
|
|
346
|
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
|
347
|
+
|
|
348
|
+
function getMermaidTheme() {
|
|
349
|
+
const theme = document.documentElement.getAttribute('data-theme');
|
|
350
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
351
|
+
const isDark = theme === 'dark' || (!theme && prefersDark);
|
|
352
|
+
return isDark ? 'dark' : 'neutral';
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
mermaid.initialize({
|
|
356
|
+
startOnLoad: true,
|
|
357
|
+
theme: getMermaidTheme()
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// Re-render mermaid diagrams when theme changes
|
|
361
|
+
window.reinitMermaid = async function() {
|
|
362
|
+
mermaid.initialize({ startOnLoad: false, theme: getMermaidTheme() });
|
|
363
|
+
const diagrams = document.querySelectorAll('.mermaid');
|
|
364
|
+
for (const el of diagrams) {
|
|
365
|
+
const code = el.getAttribute('data-mermaid-source');
|
|
366
|
+
if (code) {
|
|
367
|
+
el.innerHTML = code;
|
|
368
|
+
el.removeAttribute('data-processed');
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
await mermaid.run({ nodes: diagrams });
|
|
372
|
+
};
|
|
373
|
+
</script>
|
|
374
|
+
|
|
375
|
+
<script>
|
|
376
|
+
function toggleTheme() {
|
|
377
|
+
const html = document.documentElement;
|
|
378
|
+
const current = html.getAttribute('data-theme');
|
|
379
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
380
|
+
|
|
381
|
+
let next;
|
|
382
|
+
if (current === 'dark') {
|
|
383
|
+
next = 'light';
|
|
384
|
+
} else if (current === 'light') {
|
|
385
|
+
next = 'dark';
|
|
386
|
+
} else {
|
|
387
|
+
// No explicit theme set, toggle from system preference
|
|
388
|
+
next = prefersDark ? 'light' : 'dark';
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
html.setAttribute('data-theme', next);
|
|
392
|
+
localStorage.setItem('theme', next);
|
|
393
|
+
|
|
394
|
+
// Switch Prism theme
|
|
395
|
+
const prismLight = document.getElementById('prism-light');
|
|
396
|
+
const prismDark = document.getElementById('prism-dark');
|
|
397
|
+
if (next === 'dark') {
|
|
398
|
+
prismLight?.setAttribute('disabled', '');
|
|
399
|
+
prismDark?.removeAttribute('disabled');
|
|
400
|
+
} else {
|
|
401
|
+
prismLight?.removeAttribute('disabled');
|
|
402
|
+
prismDark?.setAttribute('disabled', '');
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Re-render mermaid diagrams with new theme
|
|
406
|
+
if (window.reinitMermaid) {
|
|
407
|
+
window.reinitMermaid();
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Slides mode hash routing
|
|
412
|
+
(function initSlidesMode() {
|
|
413
|
+
const shell = document.querySelector('.slides-shell');
|
|
414
|
+
if (!shell) return;
|
|
415
|
+
|
|
416
|
+
const slides = Array.from(document.querySelectorAll('.slide'));
|
|
417
|
+
if (!slides.length) return;
|
|
418
|
+
|
|
419
|
+
const prevBtn = document.querySelector('.slide-prev');
|
|
420
|
+
const nextBtn = document.querySelector('.slide-next');
|
|
421
|
+
const counter = document.querySelector('.slide-counter');
|
|
422
|
+
const progressBar = document.querySelector('.slide-progress-bar');
|
|
423
|
+
const navLinks = Array.from(document.querySelectorAll('.sidebar-nav a[href^="#slide-"]'));
|
|
424
|
+
let current = 0;
|
|
425
|
+
|
|
426
|
+
function setActive(n) {
|
|
427
|
+
current = Math.max(0, Math.min(n, slides.length - 1));
|
|
428
|
+
slides.forEach((slide, idx) => slide.classList.toggle('active', idx === current));
|
|
429
|
+
navLinks.forEach((link) => {
|
|
430
|
+
const active = link.getAttribute('href') === '#' + slides[current].id;
|
|
431
|
+
link.classList.toggle('active', active);
|
|
432
|
+
});
|
|
433
|
+
if (counter) counter.textContent = (current + 1) + ' / ' + slides.length;
|
|
434
|
+
if (progressBar) progressBar.style.width = (((current + 1) / slides.length) * 100) + '%';
|
|
435
|
+
if (prevBtn) prevBtn.disabled = current === 0;
|
|
436
|
+
if (nextBtn) nextBtn.disabled = current === slides.length - 1;
|
|
437
|
+
history.replaceState(null, '', '#' + slides[current].id);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function setFromHash() {
|
|
441
|
+
const hash = window.location.hash || '';
|
|
442
|
+
const idx = slides.findIndex((s) => '#' + s.id === hash);
|
|
443
|
+
if (idx >= 0) setActive(idx);
|
|
444
|
+
else setActive(0);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
prevBtn?.addEventListener('click', () => setActive(current - 1));
|
|
448
|
+
nextBtn?.addEventListener('click', () => setActive(current + 1));
|
|
449
|
+
|
|
450
|
+
document.addEventListener('keydown', (e) => {
|
|
451
|
+
if (e.key === 'ArrowRight' || e.key === ' ') {
|
|
452
|
+
e.preventDefault();
|
|
453
|
+
setActive(current + 1);
|
|
454
|
+
} else if (e.key === 'ArrowLeft') {
|
|
455
|
+
e.preventDefault();
|
|
456
|
+
setActive(current - 1);
|
|
457
|
+
} else if (e.key === 'Home') {
|
|
458
|
+
e.preventDefault();
|
|
459
|
+
setActive(0);
|
|
460
|
+
} else if (e.key === 'End') {
|
|
461
|
+
e.preventDefault();
|
|
462
|
+
setActive(slides.length - 1);
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
window.addEventListener('hashchange', setFromHash);
|
|
467
|
+
setFromHash();
|
|
468
|
+
})();
|
|
469
|
+
|
|
470
|
+
// Copy code button
|
|
471
|
+
document.querySelectorAll('.prose pre code').forEach(block => {
|
|
472
|
+
const button = document.createElement('button');
|
|
473
|
+
button.className = 'copy-button';
|
|
474
|
+
button.textContent = 'Copy';
|
|
475
|
+
button.onclick = async () => {
|
|
476
|
+
await navigator.clipboard.writeText(block.textContent);
|
|
477
|
+
button.textContent = 'Copied!';
|
|
478
|
+
setTimeout(() => button.textContent = 'Copy', 2000);
|
|
479
|
+
};
|
|
480
|
+
block.parentElement.appendChild(button);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
// Mobile nav toggle
|
|
484
|
+
function toggleNav() {
|
|
485
|
+
document.querySelector('.sidebar').classList.toggle('open');
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// Close nav when clicking outside on mobile
|
|
489
|
+
document.addEventListener('click', (e) => {
|
|
490
|
+
const sidebar = document.querySelector('.sidebar');
|
|
491
|
+
const toggle = document.querySelector('.nav-toggle');
|
|
492
|
+
if (sidebar.classList.contains('open') &&
|
|
493
|
+
!sidebar.contains(e.target) &&
|
|
494
|
+
!toggle.contains(e.target)) {
|
|
495
|
+
sidebar.classList.remove('open');
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
</script>
|
|
499
|
+
|
|
500
|
+
</body>
|
|
501
|
+
</html>
|