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,423 @@
|
|
|
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>DDR-0003: Bounded Logo Slot - Kitfly Docs</title>
|
|
7
|
+
<link rel="icon" type="image/png" sizes="32x32" href="../../assets/brand/kitfly-favicon-32.png">
|
|
8
|
+
<link rel="icon" type="image/png" sizes="64x64" href="../../assets/brand/kitfly-neon-256.png">
|
|
9
|
+
<link rel="stylesheet" href="../../styles.css">
|
|
10
|
+
<style id="kitfly-theme">
|
|
11
|
+
:root { --color-bg: #ffffff;
|
|
12
|
+
--color-bg-sidebar: #f5f7f8;
|
|
13
|
+
--color-text: #374151;
|
|
14
|
+
--color-text-muted: #6b7280;
|
|
15
|
+
--color-border: #e5e7eb;
|
|
16
|
+
--color-link: #007182;
|
|
17
|
+
--color-link-hover: #0a6172;
|
|
18
|
+
--color-accent: #152F46;
|
|
19
|
+
--color-code-bg: #f5f7f8;
|
|
20
|
+
--color-logo: #152F46;
|
|
21
|
+
--sidebar-width: 280px;
|
|
22
|
+
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
23
|
+
--font-headings: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
24
|
+
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; }
|
|
25
|
+
html { font-size: 16px; }
|
|
26
|
+
@media (prefers-color-scheme: dark) {
|
|
27
|
+
:root:not([data-theme="light"]) { --color-bg: #0d1117;
|
|
28
|
+
--color-bg-sidebar: #152F46;
|
|
29
|
+
--color-text: #e5e7eb;
|
|
30
|
+
--color-text-muted: #9ca3af;
|
|
31
|
+
--color-border: #374151;
|
|
32
|
+
--color-link: #709EA6;
|
|
33
|
+
--color-link-hover: #8fb5bc;
|
|
34
|
+
--color-accent: #f9fafb;
|
|
35
|
+
--color-code-bg: #152F46;
|
|
36
|
+
--color-logo: #f9fafb; }
|
|
37
|
+
}
|
|
38
|
+
[data-theme="dark"] { --color-bg: #0d1117;
|
|
39
|
+
--color-bg-sidebar: #152F46;
|
|
40
|
+
--color-text: #e5e7eb;
|
|
41
|
+
--color-text-muted: #9ca3af;
|
|
42
|
+
--color-border: #374151;
|
|
43
|
+
--color-link: #709EA6;
|
|
44
|
+
--color-link-hover: #8fb5bc;
|
|
45
|
+
--color-accent: #f9fafb;
|
|
46
|
+
--color-code-bg: #152F46;
|
|
47
|
+
--color-logo: #f9fafb; }
|
|
48
|
+
[data-theme="light"] { --color-bg: #ffffff;
|
|
49
|
+
--color-bg-sidebar: #f5f7f8;
|
|
50
|
+
--color-text: #374151;
|
|
51
|
+
--color-text-muted: #6b7280;
|
|
52
|
+
--color-border: #e5e7eb;
|
|
53
|
+
--color-link: #007182;
|
|
54
|
+
--color-link-hover: #0a6172;
|
|
55
|
+
--color-accent: #152F46;
|
|
56
|
+
--color-code-bg: #f5f7f8;
|
|
57
|
+
--color-logo: #152F46;
|
|
58
|
+
--sidebar-width: 280px;
|
|
59
|
+
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
60
|
+
--font-headings: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
61
|
+
--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; }
|
|
62
|
+
</style>
|
|
63
|
+
<!-- Syntax highlighting - Prism.js -->
|
|
64
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism.min.css" id="prism-light">
|
|
65
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1/themes/prism-okaidia.min.css" id="prism-dark" disabled>
|
|
66
|
+
|
|
67
|
+
<script>
|
|
68
|
+
// Apply saved theme immediately to prevent flash
|
|
69
|
+
(function() {
|
|
70
|
+
const saved = localStorage.getItem('theme');
|
|
71
|
+
if (saved) {
|
|
72
|
+
document.documentElement.setAttribute('data-theme', saved);
|
|
73
|
+
}
|
|
74
|
+
// Set Prism theme based on saved or system preference
|
|
75
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
76
|
+
const isDark = saved === 'dark' || (!saved && prefersDark);
|
|
77
|
+
if (isDark) {
|
|
78
|
+
document.getElementById('prism-light')?.setAttribute('disabled', '');
|
|
79
|
+
document.getElementById('prism-dark')?.removeAttribute('disabled');
|
|
80
|
+
}
|
|
81
|
+
})();
|
|
82
|
+
</script>
|
|
83
|
+
</head>
|
|
84
|
+
<body class="mode-docs">
|
|
85
|
+
<div class="mobile-header">
|
|
86
|
+
<button class="nav-toggle" onclick="toggleNav()" aria-label="Toggle navigation">
|
|
87
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
88
|
+
<path d="M3 12h18M3 6h18M3 18h18"/>
|
|
89
|
+
</svg>
|
|
90
|
+
</button>
|
|
91
|
+
<a href="../../" class="mobile-logo" title="Home" data-initial="K">
|
|
92
|
+
<img src="../../assets/brand/kitfly-neon-256.png" alt="Kitfly" class="logo-img logo-icon" onerror="this.onerror=null;this.style.display='none';this.parentElement.classList.add('logo-fallback')"/>
|
|
93
|
+
</a>
|
|
94
|
+
<button class="mobile-theme-toggle" onclick="toggleTheme()" title="Toggle theme" aria-label="Toggle theme">
|
|
95
|
+
<svg class="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
96
|
+
<circle cx="12" cy="12" r="5"/>
|
|
97
|
+
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
|
98
|
+
</svg>
|
|
99
|
+
<svg class="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
100
|
+
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
|
101
|
+
</svg>
|
|
102
|
+
</button>
|
|
103
|
+
</div>
|
|
104
|
+
<div class="layout">
|
|
105
|
+
<nav class="sidebar">
|
|
106
|
+
<div class="sidebar-header">
|
|
107
|
+
<div class="logo logo-icon">
|
|
108
|
+
<a href="/" class="logo-icon" data-initial="K">
|
|
109
|
+
<img src="../../assets/brand/kitfly-neon-256.png" alt="Kitfly" class="logo-img" onerror="this.onerror=null;this.style.display='none';this.parentElement.classList.add('logo-fallback')"/>
|
|
110
|
+
</a>
|
|
111
|
+
<span class="logo-text">
|
|
112
|
+
<a href="/" class="brand">Kitfly</a>
|
|
113
|
+
<a href="../../" class="product">Kitfly Docs</a>
|
|
114
|
+
</span>
|
|
115
|
+
</div>
|
|
116
|
+
<div class="header-tools">
|
|
117
|
+
<button class="theme-toggle" onclick="toggleTheme()" title="Toggle theme" aria-label="Toggle theme">
|
|
118
|
+
<svg class="icon-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
119
|
+
<circle cx="12" cy="12" r="5"/>
|
|
120
|
+
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
|
|
121
|
+
</svg>
|
|
122
|
+
<svg class="icon-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
123
|
+
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
|
124
|
+
</svg>
|
|
125
|
+
</button>
|
|
126
|
+
<div class="sidebar-meta">
|
|
127
|
+
<span class="meta-version">v0.2.1</span>
|
|
128
|
+
<span class="meta-branch">HEAD</span>
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
<div class="sidebar-nav">
|
|
133
|
+
<ul><li><a href="../../index.html" class="nav-home">Home</a></li><li><span class="nav-section">Guide</span><ul><li><a href="../../content/guide/approaches.html">approaches</a></li><li><a href="../../content/guide/features.html">features</a></li><li><a href="../../content/guide/getting-started.html">getting-started</a></li><li><a href="../../content/guide/kitfly-overview.html">kitfly-overview</a></li></ul></li><li><span class="nav-section">Templates</span><ul><li><a href="../../content/templates/crucible.html">crucible</a></li><li><a href="../../content/templates/handbook.html">handbook</a></li><li><a href="../../content/templates/minimal.html">minimal</a></li><li><a href="../../content/templates/overview.html">overview</a></li><li><a href="../../content/templates/pipeline.html">pipeline</a></li><li><a href="../../content/templates/productbook.html">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" class="active">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>DDR-0003-bounded-logo-slot</span></nav>
|
|
139
|
+
|
|
140
|
+
<h1 id="ddr-0003-bounded-logo-slot">DDR-0003: Bounded Logo Slot</h1>
|
|
141
|
+
<h2 id="status">Status</h2>
|
|
142
|
+
<p>Accepted</p>
|
|
143
|
+
<h2 id="context">Context</h2>
|
|
144
|
+
<p>Kitfly sites display a brand logo in the sidebar header. Logos come in two aspect ratios:</p>
|
|
145
|
+
<ul>
|
|
146
|
+
<li><strong>Square icons</strong> (1:1 or near-square) — app icons, monograms, favicons scaled up</li>
|
|
147
|
+
<li><strong>Wide wordmarks</strong> (3:1 or wider) — full brand names, logotypes with text</li>
|
|
148
|
+
</ul>
|
|
149
|
+
<p>The previous implementation used a fixed pixel height for the logo image, which worked for one shape but not the other. A square icon at 64px rendered fine; the same 64px height on a wide wordmark meant it consumed most of the sidebar width and pushed navigation down. Conversely, constraining width for wordmarks made square icons tiny.</p>
|
|
150
|
+
<h2 id="decision">Decision</h2>
|
|
151
|
+
<p>Use a <strong>bounded bounding-box model</strong> where the logo slot defines maximum dimensions per breakpoint, and the image fills the box while preserving its native aspect ratio.</p>
|
|
152
|
+
<h3 id="slot-dimensions">Slot Dimensions</h3>
|
|
153
|
+
<table>
|
|
154
|
+
<thead>
|
|
155
|
+
<tr>
|
|
156
|
+
<th>Breakpoint</th>
|
|
157
|
+
<th>Max Height</th>
|
|
158
|
+
<th>Max Width</th>
|
|
159
|
+
</tr>
|
|
160
|
+
</thead>
|
|
161
|
+
<tbody><tr>
|
|
162
|
+
<td>Desktop (> 1024px)</td>
|
|
163
|
+
<td>64px</td>
|
|
164
|
+
<td>180px</td>
|
|
165
|
+
</tr>
|
|
166
|
+
<tr>
|
|
167
|
+
<td>Tablet (≤ 1024px)</td>
|
|
168
|
+
<td>56px</td>
|
|
169
|
+
<td>150px</td>
|
|
170
|
+
</tr>
|
|
171
|
+
<tr>
|
|
172
|
+
<td>Mobile (≤ 768px)</td>
|
|
173
|
+
<td>48px</td>
|
|
174
|
+
<td>130px</td>
|
|
175
|
+
</tr>
|
|
176
|
+
</tbody></table>
|
|
177
|
+
<h3 id="css-implementation">CSS Implementation</h3>
|
|
178
|
+
<pre><code class="language-css">.logo-icon {
|
|
179
|
+
height: 64px;
|
|
180
|
+
width: auto;
|
|
181
|
+
max-width: 180px;
|
|
182
|
+
}
|
|
183
|
+
</code></pre>
|
|
184
|
+
<p>The key properties:</p>
|
|
185
|
+
<ul>
|
|
186
|
+
<li><code>height</code> sets the box height (the dominant constraint for square icons)</li>
|
|
187
|
+
<li><code>width: auto</code> preserves aspect ratio</li>
|
|
188
|
+
<li><code>max-width</code> prevents wide wordmarks from overflowing the sidebar</li>
|
|
189
|
+
</ul>
|
|
190
|
+
<p>For wordmark logos, the <code>.logo-wordmark</code> class switches the constraint axis:</p>
|
|
191
|
+
<pre><code class="language-css">.logo.logo-wordmark .logo-img {
|
|
192
|
+
max-width: 180px;
|
|
193
|
+
height: auto;
|
|
194
|
+
max-height: 64px;
|
|
195
|
+
}
|
|
196
|
+
</code></pre>
|
|
197
|
+
<h3 id="logotype-configuration">logoType Configuration</h3>
|
|
198
|
+
<p><code>site.yaml</code> supports <code>brand.logoType</code> to select the rendering mode:</p>
|
|
199
|
+
<table>
|
|
200
|
+
<thead>
|
|
201
|
+
<tr>
|
|
202
|
+
<th>Value</th>
|
|
203
|
+
<th>Behavior</th>
|
|
204
|
+
</tr>
|
|
205
|
+
</thead>
|
|
206
|
+
<tbody><tr>
|
|
207
|
+
<td><code>"icon"</code> (default)</td>
|
|
208
|
+
<td>Height-dominant constraint, square/near-square</td>
|
|
209
|
+
</tr>
|
|
210
|
+
<tr>
|
|
211
|
+
<td><code>"wordmark"</code></td>
|
|
212
|
+
<td>Width-dominant constraint, wide aspect ratio</td>
|
|
213
|
+
</tr>
|
|
214
|
+
</tbody></table>
|
|
215
|
+
<p>The bundle system propagates <code>logoType</code> via <code>buildBundleSidebarHeader()</code> to ensure parity between build and bundle output.</p>
|
|
216
|
+
<h3 id="supported-formats">Supported Formats</h3>
|
|
217
|
+
<ul>
|
|
218
|
+
<li><strong>PNG</strong>: Recommended for icons. Use <code>kitfly-logo-128.png</code> at 128px for 2x retina clarity in the 64px slot.</li>
|
|
219
|
+
<li><strong>SVG</strong>: Supported but requires a tightly-cropped <code>viewBox</code>. An oversized canvas (e.g., A4 page <code>viewBox="0 0 210 297"</code>) will render the artwork too small within the bounded slot.</li>
|
|
220
|
+
</ul>
|
|
221
|
+
<h2 id="consequences">Consequences</h2>
|
|
222
|
+
<h3 id="positive">Positive</h3>
|
|
223
|
+
<ul>
|
|
224
|
+
<li>Both icon and wordmark logos render cleanly without CSS customization</li>
|
|
225
|
+
<li>Responsive scaling is automatic — one set of breakpoints handles both shapes</li>
|
|
226
|
+
<li>No logo distortion — aspect ratio is always preserved</li>
|
|
227
|
+
<li>Bundle output matches static build (logoType propagation)</li>
|
|
228
|
+
</ul>
|
|
229
|
+
<h3 id="negative">Negative</h3>
|
|
230
|
+
<ul>
|
|
231
|
+
<li>SVG logos with oversized viewBox render poorly — users must crop the viewBox to artwork bounds (documented in configuration reference)</li>
|
|
232
|
+
<li>Two rendering modes (<code>icon</code> vs <code>wordmark</code>) add a configuration choice — mitigated by defaulting to <code>icon</code> which handles most cases</li>
|
|
233
|
+
</ul>
|
|
234
|
+
<h2 id="alternatives-considered">Alternatives Considered</h2>
|
|
235
|
+
<h3 id="fixed-pixel-dimensions">Fixed pixel dimensions</h3>
|
|
236
|
+
<p>Single <code>width: 120px; height: 40px</code> for all logos. Rejected because it distorts non-matching aspect ratios and doesn't adapt to breakpoints.</p>
|
|
237
|
+
<h3 id="percentage-based-sizing">Percentage-based sizing</h3>
|
|
238
|
+
<p><code>width: 60%</code> of sidebar. Rejected because it couples logo size to sidebar width and produces inconsistent results across breakpoints (280px desktop vs overlay mobile).</p>
|
|
239
|
+
<h3 id="user-specified-dimensions-in-siteyaml">User-specified dimensions in site.yaml</h3>
|
|
240
|
+
<p>Let users set <code>logo.width</code> and <code>logo.height</code> in config. Rejected as over-engineering — the bounded box handles the common cases, and users can override via custom CSS if needed.</p>
|
|
241
|
+
|
|
242
|
+
</article>
|
|
243
|
+
<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="#slot-dimensions">Slot Dimensions</a></li><li class="toc-h3"><a href="#css-implementation">CSS Implementation</a></li><li class="toc-h3"><a href="#logotype-configuration">logoType Configuration</a></li><li class="toc-h3"><a href="#supported-formats">Supported Formats</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><a href="#alternatives-considered">Alternatives Considered</a></li><li class="toc-h3"><a href="#fixed-pixel-dimensions">Fixed pixel dimensions</a></li><li class="toc-h3"><a href="#percentage-based-sizing">Percentage-based sizing</a></li><li class="toc-h3"><a href="#user-specified-dimensions-in-siteyaml">User-specified dimensions in site.yaml</a></li></ul></aside>
|
|
244
|
+
</main>
|
|
245
|
+
</div>
|
|
246
|
+
|
|
247
|
+
<footer class="site-footer">
|
|
248
|
+
<div class="footer-content">
|
|
249
|
+
<div class="footer-left">
|
|
250
|
+
<span class="footer-version">v0.2.1</span>
|
|
251
|
+
<span class="footer-separator">·</span>
|
|
252
|
+
<span class="footer-commit" title="Commit: 30dfc01">Published 2026-02-15</span>
|
|
253
|
+
</div>
|
|
254
|
+
<div class="footer-center">
|
|
255
|
+
<span class="footer-copyright"><a href="https://3leaps.net" class="footer-link">© 2026 3 Leaps, LLC</a></span>
|
|
256
|
+
<span class="footer-separator">·</span><a href="/" class="footer-link">Kitfly</a>
|
|
257
|
+
</div>
|
|
258
|
+
<div class="footer-right">
|
|
259
|
+
<a href="https://kitfly.dev" class="footer-link">Built with Kitfly</a>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
</footer>
|
|
263
|
+
<!-- Syntax highlighting - Prism.js -->
|
|
264
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-core.min.js"></script>
|
|
265
|
+
<script src="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js"></script>
|
|
266
|
+
<!-- Mermaid diagram support -->
|
|
267
|
+
<script type="module">
|
|
268
|
+
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
|
269
|
+
|
|
270
|
+
function getMermaidTheme() {
|
|
271
|
+
const theme = document.documentElement.getAttribute('data-theme');
|
|
272
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
273
|
+
const isDark = theme === 'dark' || (!theme && prefersDark);
|
|
274
|
+
return isDark ? 'dark' : 'neutral';
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
mermaid.initialize({
|
|
278
|
+
startOnLoad: true,
|
|
279
|
+
theme: getMermaidTheme()
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// Re-render mermaid diagrams when theme changes
|
|
283
|
+
window.reinitMermaid = async function() {
|
|
284
|
+
mermaid.initialize({ startOnLoad: false, theme: getMermaidTheme() });
|
|
285
|
+
const diagrams = document.querySelectorAll('.mermaid');
|
|
286
|
+
for (const el of diagrams) {
|
|
287
|
+
const code = el.getAttribute('data-mermaid-source');
|
|
288
|
+
if (code) {
|
|
289
|
+
el.innerHTML = code;
|
|
290
|
+
el.removeAttribute('data-processed');
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
await mermaid.run({ nodes: diagrams });
|
|
294
|
+
};
|
|
295
|
+
</script>
|
|
296
|
+
|
|
297
|
+
<script>
|
|
298
|
+
function toggleTheme() {
|
|
299
|
+
const html = document.documentElement;
|
|
300
|
+
const current = html.getAttribute('data-theme');
|
|
301
|
+
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
302
|
+
|
|
303
|
+
let next;
|
|
304
|
+
if (current === 'dark') {
|
|
305
|
+
next = 'light';
|
|
306
|
+
} else if (current === 'light') {
|
|
307
|
+
next = 'dark';
|
|
308
|
+
} else {
|
|
309
|
+
// No explicit theme set, toggle from system preference
|
|
310
|
+
next = prefersDark ? 'light' : 'dark';
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
html.setAttribute('data-theme', next);
|
|
314
|
+
localStorage.setItem('theme', next);
|
|
315
|
+
|
|
316
|
+
// Switch Prism theme
|
|
317
|
+
const prismLight = document.getElementById('prism-light');
|
|
318
|
+
const prismDark = document.getElementById('prism-dark');
|
|
319
|
+
if (next === 'dark') {
|
|
320
|
+
prismLight?.setAttribute('disabled', '');
|
|
321
|
+
prismDark?.removeAttribute('disabled');
|
|
322
|
+
} else {
|
|
323
|
+
prismLight?.removeAttribute('disabled');
|
|
324
|
+
prismDark?.setAttribute('disabled', '');
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Re-render mermaid diagrams with new theme
|
|
328
|
+
if (window.reinitMermaid) {
|
|
329
|
+
window.reinitMermaid();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Slides mode hash routing
|
|
334
|
+
(function initSlidesMode() {
|
|
335
|
+
const shell = document.querySelector('.slides-shell');
|
|
336
|
+
if (!shell) return;
|
|
337
|
+
|
|
338
|
+
const slides = Array.from(document.querySelectorAll('.slide'));
|
|
339
|
+
if (!slides.length) return;
|
|
340
|
+
|
|
341
|
+
const prevBtn = document.querySelector('.slide-prev');
|
|
342
|
+
const nextBtn = document.querySelector('.slide-next');
|
|
343
|
+
const counter = document.querySelector('.slide-counter');
|
|
344
|
+
const progressBar = document.querySelector('.slide-progress-bar');
|
|
345
|
+
const navLinks = Array.from(document.querySelectorAll('.sidebar-nav a[href^="#slide-"]'));
|
|
346
|
+
let current = 0;
|
|
347
|
+
|
|
348
|
+
function setActive(n) {
|
|
349
|
+
current = Math.max(0, Math.min(n, slides.length - 1));
|
|
350
|
+
slides.forEach((slide, idx) => slide.classList.toggle('active', idx === current));
|
|
351
|
+
navLinks.forEach((link) => {
|
|
352
|
+
const active = link.getAttribute('href') === '#' + slides[current].id;
|
|
353
|
+
link.classList.toggle('active', active);
|
|
354
|
+
});
|
|
355
|
+
if (counter) counter.textContent = (current + 1) + ' / ' + slides.length;
|
|
356
|
+
if (progressBar) progressBar.style.width = (((current + 1) / slides.length) * 100) + '%';
|
|
357
|
+
if (prevBtn) prevBtn.disabled = current === 0;
|
|
358
|
+
if (nextBtn) nextBtn.disabled = current === slides.length - 1;
|
|
359
|
+
history.replaceState(null, '', '#' + slides[current].id);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function setFromHash() {
|
|
363
|
+
const hash = window.location.hash || '';
|
|
364
|
+
const idx = slides.findIndex((s) => '#' + s.id === hash);
|
|
365
|
+
if (idx >= 0) setActive(idx);
|
|
366
|
+
else setActive(0);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
prevBtn?.addEventListener('click', () => setActive(current - 1));
|
|
370
|
+
nextBtn?.addEventListener('click', () => setActive(current + 1));
|
|
371
|
+
|
|
372
|
+
document.addEventListener('keydown', (e) => {
|
|
373
|
+
if (e.key === 'ArrowRight' || e.key === ' ') {
|
|
374
|
+
e.preventDefault();
|
|
375
|
+
setActive(current + 1);
|
|
376
|
+
} else if (e.key === 'ArrowLeft') {
|
|
377
|
+
e.preventDefault();
|
|
378
|
+
setActive(current - 1);
|
|
379
|
+
} else if (e.key === 'Home') {
|
|
380
|
+
e.preventDefault();
|
|
381
|
+
setActive(0);
|
|
382
|
+
} else if (e.key === 'End') {
|
|
383
|
+
e.preventDefault();
|
|
384
|
+
setActive(slides.length - 1);
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
window.addEventListener('hashchange', setFromHash);
|
|
389
|
+
setFromHash();
|
|
390
|
+
})();
|
|
391
|
+
|
|
392
|
+
// Copy code button
|
|
393
|
+
document.querySelectorAll('.prose pre code').forEach(block => {
|
|
394
|
+
const button = document.createElement('button');
|
|
395
|
+
button.className = 'copy-button';
|
|
396
|
+
button.textContent = 'Copy';
|
|
397
|
+
button.onclick = async () => {
|
|
398
|
+
await navigator.clipboard.writeText(block.textContent);
|
|
399
|
+
button.textContent = 'Copied!';
|
|
400
|
+
setTimeout(() => button.textContent = 'Copy', 2000);
|
|
401
|
+
};
|
|
402
|
+
block.parentElement.appendChild(button);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
// Mobile nav toggle
|
|
406
|
+
function toggleNav() {
|
|
407
|
+
document.querySelector('.sidebar').classList.toggle('open');
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Close nav when clicking outside on mobile
|
|
411
|
+
document.addEventListener('click', (e) => {
|
|
412
|
+
const sidebar = document.querySelector('.sidebar');
|
|
413
|
+
const toggle = document.querySelector('.nav-toggle');
|
|
414
|
+
if (sidebar.classList.contains('open') &&
|
|
415
|
+
!sidebar.contains(e.target) &&
|
|
416
|
+
!toggle.contains(e.target)) {
|
|
417
|
+
sidebar.classList.remove('open');
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
</script>
|
|
421
|
+
|
|
422
|
+
</body>
|
|
423
|
+
</html>
|