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,491 @@
|
|
|
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>ADR-0001: Minimalist Site Code - 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">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" class="active">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="../../docs/userguide/cli/build.html">Docs</a><span class="separator">›</span><a href="../../docs/decisions/ADR-0001-minimalist-site-code.html">Decisions</a><span class="separator">›</span><span>ADR-0001-minimalist-site-code</span></nav>
|
|
139
|
+
|
|
140
|
+
<h1 id="adr-0001-minimalist-site-code">ADR-0001: Minimalist Site Code</h1>
|
|
141
|
+
<h2 id="status">Status</h2>
|
|
142
|
+
<p>Accepted</p>
|
|
143
|
+
<h2 id="context">Context</h2>
|
|
144
|
+
<p>When users run <code>kitfly init</code>, they receive a complete, standalone site with rendering code. This code becomes <strong>theirs</strong> — they can modify it, version it, and maintain it.</p>
|
|
145
|
+
<p>The site code must be:</p>
|
|
146
|
+
<ul>
|
|
147
|
+
<li><strong>Small</strong>: Understandable in an afternoon</li>
|
|
148
|
+
<li><strong>Reviewable</strong>: A security-conscious user can audit it</li>
|
|
149
|
+
<li><strong>Modifiable</strong>: Users can customize without fear</li>
|
|
150
|
+
<li><strong>Maintainable</strong>: One dependency, no churn</li>
|
|
151
|
+
</ul>
|
|
152
|
+
<p>This ADR defines what belongs in site code vs. what stays in the kitfly CLI.</p>
|
|
153
|
+
<h2 id="decision">Decision</h2>
|
|
154
|
+
<h3 id="site-code-thresholds">Site Code Thresholds</h3>
|
|
155
|
+
<p>The site code that <code>kitfly init</code> copies should stay within these bounds:</p>
|
|
156
|
+
<table>
|
|
157
|
+
<thead>
|
|
158
|
+
<tr>
|
|
159
|
+
<th>Metric</th>
|
|
160
|
+
<th>Target</th>
|
|
161
|
+
<th>Hard Limit</th>
|
|
162
|
+
</tr>
|
|
163
|
+
</thead>
|
|
164
|
+
<tbody><tr>
|
|
165
|
+
<td>Total lines (scripts/)</td>
|
|
166
|
+
<td>~500</td>
|
|
167
|
+
<td>800</td>
|
|
168
|
+
</tr>
|
|
169
|
+
<tr>
|
|
170
|
+
<td>Dependencies</td>
|
|
171
|
+
<td>1 (marked)</td>
|
|
172
|
+
<td>2</td>
|
|
173
|
+
</tr>
|
|
174
|
+
<tr>
|
|
175
|
+
<td>Files copied</td>
|
|
176
|
+
<td>~10</td>
|
|
177
|
+
<td>15</td>
|
|
178
|
+
</tr>
|
|
179
|
+
</tbody></table>
|
|
180
|
+
<h3 id="what-belongs-in-site-code">What Belongs in Site Code</h3>
|
|
181
|
+
<table>
|
|
182
|
+
<thead>
|
|
183
|
+
<tr>
|
|
184
|
+
<th>Component</th>
|
|
185
|
+
<th>Purpose</th>
|
|
186
|
+
<th>Approximate Size</th>
|
|
187
|
+
</tr>
|
|
188
|
+
</thead>
|
|
189
|
+
<tbody><tr>
|
|
190
|
+
<td><code>scripts/dev.ts</code></td>
|
|
191
|
+
<td>Dev server with hot reload</td>
|
|
192
|
+
<td>~400 lines</td>
|
|
193
|
+
</tr>
|
|
194
|
+
<tr>
|
|
195
|
+
<td><code>scripts/build.ts</code></td>
|
|
196
|
+
<td>Static site generation</td>
|
|
197
|
+
<td>~350 lines</td>
|
|
198
|
+
</tr>
|
|
199
|
+
<tr>
|
|
200
|
+
<td><code>scripts/bundle.ts</code></td>
|
|
201
|
+
<td>Single-file HTML output</td>
|
|
202
|
+
<td>~250 lines</td>
|
|
203
|
+
</tr>
|
|
204
|
+
<tr>
|
|
205
|
+
<td><code>src/theme.ts</code></td>
|
|
206
|
+
<td>Theme loading and CSS generation</td>
|
|
207
|
+
<td>~150 lines</td>
|
|
208
|
+
</tr>
|
|
209
|
+
<tr>
|
|
210
|
+
<td><code>src/engine.ts</code></td>
|
|
211
|
+
<td>Path utilities</td>
|
|
212
|
+
<td>~20 lines</td>
|
|
213
|
+
</tr>
|
|
214
|
+
<tr>
|
|
215
|
+
<td><code>src/site/template.html</code></td>
|
|
216
|
+
<td>HTML template</td>
|
|
217
|
+
<td>~150 lines</td>
|
|
218
|
+
</tr>
|
|
219
|
+
<tr>
|
|
220
|
+
<td><code>src/site/styles.css</code></td>
|
|
221
|
+
<td>Default styles</td>
|
|
222
|
+
<td>~400 lines</td>
|
|
223
|
+
</tr>
|
|
224
|
+
</tbody></table>
|
|
225
|
+
<p><strong>Rule of thumb</strong>: If it can be done with CSS, vanilla JS under 50 lines, or a marked plugin, it belongs in site code.</p>
|
|
226
|
+
<h3 id="what-stays-in-kitfly-cli">What Stays in Kitfly CLI</h3>
|
|
227
|
+
<table>
|
|
228
|
+
<thead>
|
|
229
|
+
<tr>
|
|
230
|
+
<th>Component</th>
|
|
231
|
+
<th>Purpose</th>
|
|
232
|
+
<th>Reason</th>
|
|
233
|
+
</tr>
|
|
234
|
+
</thead>
|
|
235
|
+
<tbody><tr>
|
|
236
|
+
<td><code>src/cli.ts</code></td>
|
|
237
|
+
<td>CLI entry point</td>
|
|
238
|
+
<td>Users don't need this</td>
|
|
239
|
+
</tr>
|
|
240
|
+
<tr>
|
|
241
|
+
<td><code>src/commands/init.ts</code></td>
|
|
242
|
+
<td>Project scaffolding</td>
|
|
243
|
+
<td>Meta-tooling</td>
|
|
244
|
+
</tr>
|
|
245
|
+
<tr>
|
|
246
|
+
<td><code>src/commands/update.ts</code></td>
|
|
247
|
+
<td>Site code updates</td>
|
|
248
|
+
<td>Meta-tooling</td>
|
|
249
|
+
</tr>
|
|
250
|
+
<tr>
|
|
251
|
+
<td><code>content/</code></td>
|
|
252
|
+
<td>Kitfly's own docs</td>
|
|
253
|
+
<td>Not user content</td>
|
|
254
|
+
</tr>
|
|
255
|
+
<tr>
|
|
256
|
+
<td><code>assets/brand/</code></td>
|
|
257
|
+
<td>Kitfly branding</td>
|
|
258
|
+
<td>Users have their own</td>
|
|
259
|
+
</tr>
|
|
260
|
+
</tbody></table>
|
|
261
|
+
<h3 id="feature-evaluation">Feature Evaluation</h3>
|
|
262
|
+
<p>Before adding any feature to site code:</p>
|
|
263
|
+
<ol>
|
|
264
|
+
<li><strong>Check the line budget</strong> — Will this exceed 800 lines?</li>
|
|
265
|
+
<li><strong>Check the dependency count</strong> — Does this require a new dependency?</li>
|
|
266
|
+
<li><strong>Check the complexity</strong> — Can a user understand this in an afternoon?</li>
|
|
267
|
+
<li><strong>Check the necessity</strong> — Is this core rendering, or CLI convenience?</li>
|
|
268
|
+
</ol>
|
|
269
|
+
<p>Features that fail these checks should:</p>
|
|
270
|
+
<ul>
|
|
271
|
+
<li>Stay in the kitfly CLI (not copied to user sites)</li>
|
|
272
|
+
<li>Be implemented as optional user customization</li>
|
|
273
|
+
<li>Trigger a discussion about whether we're solving the right problem</li>
|
|
274
|
+
</ul>
|
|
275
|
+
<h3 id="migration-path">Migration Path</h3>
|
|
276
|
+
<p>If site code grows beyond thresholds:</p>
|
|
277
|
+
<ol>
|
|
278
|
+
<li><strong>Refactor first</strong> — Can we simplify?</li>
|
|
279
|
+
<li><strong>Extract to CLI</strong> — Move non-essential features to kitfly CLI</li>
|
|
280
|
+
<li><strong>Document the tradeoff</strong> — If complexity is unavoidable, explain why</li>
|
|
281
|
+
</ol>
|
|
282
|
+
<p>Users who need more should migrate to Astro, VitePress, or similar. Their content is just markdown — migration is straightforward.</p>
|
|
283
|
+
<h2 id="consequences">Consequences</h2>
|
|
284
|
+
<h3 id="positive">Positive</h3>
|
|
285
|
+
<ul>
|
|
286
|
+
<li>Users receive code they can actually understand</li>
|
|
287
|
+
<li>Security review is feasible (small surface area)</li>
|
|
288
|
+
<li>Modifications don't require framework knowledge</li>
|
|
289
|
+
<li>One <code>bun install</code> and they're running</li>
|
|
290
|
+
</ul>
|
|
291
|
+
<h3 id="negative">Negative</h3>
|
|
292
|
+
<ul>
|
|
293
|
+
<li>Some features require discipline to implement minimally</li>
|
|
294
|
+
<li>Visual sophistication bounded by CSS capabilities</li>
|
|
295
|
+
<li>Power users may want more than we provide</li>
|
|
296
|
+
</ul>
|
|
297
|
+
<h3 id="neutral">Neutral</h3>
|
|
298
|
+
<ul>
|
|
299
|
+
<li>Feature requests require threshold evaluation</li>
|
|
300
|
+
<li>"Can we add X?" becomes a structured conversation</li>
|
|
301
|
+
</ul>
|
|
302
|
+
<h2 id="compliance">Compliance</h2>
|
|
303
|
+
<p>All changes to files under <code>scripts/</code>, <code>src/site/</code>, <code>src/engine.ts</code>, or <code>src/theme.ts</code> must consider this ADR. These files are copied to user projects.</p>
|
|
304
|
+
<h2 id="references">References</h2>
|
|
305
|
+
<ul>
|
|
306
|
+
<li><a href="../../content/guide/kitfly-overview.md">Kitfly Overview</a> — Product philosophy</li>
|
|
307
|
+
<li>Handbook ADR-0001 — Original minimalist thresholds</li>
|
|
308
|
+
</ul>
|
|
309
|
+
|
|
310
|
+
</article>
|
|
311
|
+
<aside class="toc"><span class="toc-title">On this page</span><ul><li><a href="#status">Status</a></li><li><a href="#context">Context</a></li><li><a href="#decision">Decision</a></li><li class="toc-h3"><a href="#site-code-thresholds">Site Code Thresholds</a></li><li class="toc-h3"><a href="#what-belongs-in-site-code">What Belongs in Site Code</a></li><li class="toc-h3"><a href="#what-stays-in-kitfly-cli">What Stays in Kitfly CLI</a></li><li class="toc-h3"><a href="#feature-evaluation">Feature Evaluation</a></li><li class="toc-h3"><a href="#migration-path">Migration Path</a></li><li><a href="#consequences">Consequences</a></li><li class="toc-h3"><a href="#positive">Positive</a></li><li class="toc-h3"><a href="#negative">Negative</a></li><li class="toc-h3"><a href="#neutral">Neutral</a></li><li><a href="#compliance">Compliance</a></li><li><a href="#references">References</a></li></ul></aside>
|
|
312
|
+
</main>
|
|
313
|
+
</div>
|
|
314
|
+
|
|
315
|
+
<footer class="site-footer">
|
|
316
|
+
<div class="footer-content">
|
|
317
|
+
<div class="footer-left">
|
|
318
|
+
<span class="footer-version">v0.2.0</span>
|
|
319
|
+
<span class="footer-separator">·</span>
|
|
320
|
+
<span class="footer-commit" title="Commit: 33ccd68">Published 2026-02-15</span>
|
|
321
|
+
</div>
|
|
322
|
+
<div class="footer-center">
|
|
323
|
+
<span class="footer-copyright"><a href="https://3leaps.net" class="footer-link">© 2026 3 Leaps, LLC</a></span>
|
|
324
|
+
<span class="footer-separator">·</span><a href="/" class="footer-link">Kitfly</a>
|
|
325
|
+
</div>
|
|
326
|
+
<div class="footer-right">
|
|
327
|
+
<a href="https://kitfly.dev" class="footer-link">Built with Kitfly</a>
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
</footer>
|
|
331
|
+
<!-- Syntax highlighting - Prism.js -->
|
|
332
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-core.min.js"></script>
|
|
333
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js"></script>
|
|
334
|
+
<!-- Mermaid diagram support -->
|
|
335
|
+
<script type="module">
|
|
336
|
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
|
337
|
+
|
|
338
|
+
function getMermaidTheme() {
|
|
339
|
+
const theme = document.documentElement.getAttribute('data-theme');
|
|
340
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
341
|
+
const isDark = theme === 'dark' || (!theme && prefersDark);
|
|
342
|
+
return isDark ? 'dark' : 'neutral';
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
mermaid.initialize({
|
|
346
|
+
startOnLoad: true,
|
|
347
|
+
theme: getMermaidTheme()
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
// Re-render mermaid diagrams when theme changes
|
|
351
|
+
window.reinitMermaid = async function() {
|
|
352
|
+
mermaid.initialize({ startOnLoad: false, theme: getMermaidTheme() });
|
|
353
|
+
const diagrams = document.querySelectorAll('.mermaid');
|
|
354
|
+
for (const el of diagrams) {
|
|
355
|
+
const code = el.getAttribute('data-mermaid-source');
|
|
356
|
+
if (code) {
|
|
357
|
+
el.innerHTML = code;
|
|
358
|
+
el.removeAttribute('data-processed');
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
await mermaid.run({ nodes: diagrams });
|
|
362
|
+
};
|
|
363
|
+
</script>
|
|
364
|
+
|
|
365
|
+
<script>
|
|
366
|
+
function toggleTheme() {
|
|
367
|
+
const html = document.documentElement;
|
|
368
|
+
const current = html.getAttribute('data-theme');
|
|
369
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
370
|
+
|
|
371
|
+
let next;
|
|
372
|
+
if (current === 'dark') {
|
|
373
|
+
next = 'light';
|
|
374
|
+
} else if (current === 'light') {
|
|
375
|
+
next = 'dark';
|
|
376
|
+
} else {
|
|
377
|
+
// No explicit theme set, toggle from system preference
|
|
378
|
+
next = prefersDark ? 'light' : 'dark';
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
html.setAttribute('data-theme', next);
|
|
382
|
+
localStorage.setItem('theme', next);
|
|
383
|
+
|
|
384
|
+
// Switch Prism theme
|
|
385
|
+
const prismLight = document.getElementById('prism-light');
|
|
386
|
+
const prismDark = document.getElementById('prism-dark');
|
|
387
|
+
if (next === 'dark') {
|
|
388
|
+
prismLight?.setAttribute('disabled', '');
|
|
389
|
+
prismDark?.removeAttribute('disabled');
|
|
390
|
+
} else {
|
|
391
|
+
prismLight?.removeAttribute('disabled');
|
|
392
|
+
prismDark?.setAttribute('disabled', '');
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Re-render mermaid diagrams with new theme
|
|
396
|
+
if (window.reinitMermaid) {
|
|
397
|
+
window.reinitMermaid();
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Slides mode hash routing
|
|
402
|
+
(function initSlidesMode() {
|
|
403
|
+
const shell = document.querySelector('.slides-shell');
|
|
404
|
+
if (!shell) return;
|
|
405
|
+
|
|
406
|
+
const slides = Array.from(document.querySelectorAll('.slide'));
|
|
407
|
+
if (!slides.length) return;
|
|
408
|
+
|
|
409
|
+
const prevBtn = document.querySelector('.slide-prev');
|
|
410
|
+
const nextBtn = document.querySelector('.slide-next');
|
|
411
|
+
const counter = document.querySelector('.slide-counter');
|
|
412
|
+
const progressBar = document.querySelector('.slide-progress-bar');
|
|
413
|
+
const navLinks = Array.from(document.querySelectorAll('.sidebar-nav a[href^="#slide-"]'));
|
|
414
|
+
let current = 0;
|
|
415
|
+
|
|
416
|
+
function setActive(n) {
|
|
417
|
+
current = Math.max(0, Math.min(n, slides.length - 1));
|
|
418
|
+
slides.forEach((slide, idx) => slide.classList.toggle('active', idx === current));
|
|
419
|
+
navLinks.forEach((link) => {
|
|
420
|
+
const active = link.getAttribute('href') === '#' + slides[current].id;
|
|
421
|
+
link.classList.toggle('active', active);
|
|
422
|
+
});
|
|
423
|
+
if (counter) counter.textContent = (current + 1) + ' / ' + slides.length;
|
|
424
|
+
if (progressBar) progressBar.style.width = (((current + 1) / slides.length) * 100) + '%';
|
|
425
|
+
if (prevBtn) prevBtn.disabled = current === 0;
|
|
426
|
+
if (nextBtn) nextBtn.disabled = current === slides.length - 1;
|
|
427
|
+
history.replaceState(null, '', '#' + slides[current].id);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
function setFromHash() {
|
|
431
|
+
const hash = window.location.hash || '';
|
|
432
|
+
const idx = slides.findIndex((s) => '#' + s.id === hash);
|
|
433
|
+
if (idx >= 0) setActive(idx);
|
|
434
|
+
else setActive(0);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
prevBtn?.addEventListener('click', () => setActive(current - 1));
|
|
438
|
+
nextBtn?.addEventListener('click', () => setActive(current + 1));
|
|
439
|
+
|
|
440
|
+
document.addEventListener('keydown', (e) => {
|
|
441
|
+
if (e.key === 'ArrowRight' || e.key === ' ') {
|
|
442
|
+
e.preventDefault();
|
|
443
|
+
setActive(current + 1);
|
|
444
|
+
} else if (e.key === 'ArrowLeft') {
|
|
445
|
+
e.preventDefault();
|
|
446
|
+
setActive(current - 1);
|
|
447
|
+
} else if (e.key === 'Home') {
|
|
448
|
+
e.preventDefault();
|
|
449
|
+
setActive(0);
|
|
450
|
+
} else if (e.key === 'End') {
|
|
451
|
+
e.preventDefault();
|
|
452
|
+
setActive(slides.length - 1);
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
window.addEventListener('hashchange', setFromHash);
|
|
457
|
+
setFromHash();
|
|
458
|
+
})();
|
|
459
|
+
|
|
460
|
+
// Copy code button
|
|
461
|
+
document.querySelectorAll('.prose pre code').forEach(block => {
|
|
462
|
+
const button = document.createElement('button');
|
|
463
|
+
button.className = 'copy-button';
|
|
464
|
+
button.textContent = 'Copy';
|
|
465
|
+
button.onclick = async () => {
|
|
466
|
+
await navigator.clipboard.writeText(block.textContent);
|
|
467
|
+
button.textContent = 'Copied!';
|
|
468
|
+
setTimeout(() => button.textContent = 'Copy', 2000);
|
|
469
|
+
};
|
|
470
|
+
block.parentElement.appendChild(button);
|
|
471
|
+
});
|
|
472
|
+
|
|
473
|
+
// Mobile nav toggle
|
|
474
|
+
function toggleNav() {
|
|
475
|
+
document.querySelector('.sidebar').classList.toggle('open');
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Close nav when clicking outside on mobile
|
|
479
|
+
document.addEventListener('click', (e) => {
|
|
480
|
+
const sidebar = document.querySelector('.sidebar');
|
|
481
|
+
const toggle = document.querySelector('.nav-toggle');
|
|
482
|
+
if (sidebar.classList.contains('open') &&
|
|
483
|
+
!sidebar.contains(e.target) &&
|
|
484
|
+
!toggle.contains(e.target)) {
|
|
485
|
+
sidebar.classList.remove('open');
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
</script>
|
|
489
|
+
|
|
490
|
+
</body>
|
|
491
|
+
</html>
|