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,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "ADR-0003: Single-File Bundle Output"
|
|
3
|
+
description: "Kitfly produces a self-contained HTML file as an alternative to static site build"
|
|
4
|
+
author: "deliverylead"
|
|
5
|
+
supervised_by: "@3leapsdave"
|
|
6
|
+
date: "2026-02-09"
|
|
7
|
+
status: "accepted"
|
|
8
|
+
tags: ["adr", "bundle", "architecture", "sharing"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# ADR-0003: Single-File Bundle Output
|
|
12
|
+
|
|
13
|
+
## Status
|
|
14
|
+
|
|
15
|
+
Accepted
|
|
16
|
+
|
|
17
|
+
## Context
|
|
18
|
+
|
|
19
|
+
Documentation is often shared outside of web hosting — via email, Slack uploads, shared drives, or USB handoff. Traditional static site generators produce a directory of HTML, CSS, JS, and images that require a web server or careful relative-path handling to open locally.
|
|
20
|
+
|
|
21
|
+
Kitfly needed a sharing model that works without any infrastructure: one file, any browser, no server.
|
|
22
|
+
|
|
23
|
+
## Decision
|
|
24
|
+
|
|
25
|
+
Implement `kitfly bundle` as a first-class output mode alongside `kitfly build`. The bundle produces a **single self-contained HTML file** with all dependencies inlined.
|
|
26
|
+
|
|
27
|
+
### What Gets Inlined
|
|
28
|
+
|
|
29
|
+
| Asset | Inlining Strategy |
|
|
30
|
+
| ------------------------------ | ------------------------------------------- |
|
|
31
|
+
| CSS (styles.css) | `<style>` block in `<head>` |
|
|
32
|
+
| Theme CSS | Generated `<style id="kitfly-theme">` block |
|
|
33
|
+
| Images (PNG, JPG, SVG, GIF) | Base64 data URIs in `<img src>` |
|
|
34
|
+
| Brand logo + favicon | Base64 data URIs |
|
|
35
|
+
| Prism.js (syntax highlighting) | Full JS inlined in `<script>` |
|
|
36
|
+
| Mermaid (diagrams) | Full JS inlined in `<script>` |
|
|
37
|
+
| Dark mode toggle | Inline `<script>` |
|
|
38
|
+
| All page content | Inline HTML sections with `id` anchors |
|
|
39
|
+
|
|
40
|
+
### Navigation Model
|
|
41
|
+
|
|
42
|
+
The bundle uses **hash-based navigation** rather than page-per-file:
|
|
43
|
+
|
|
44
|
+
- Each content page becomes a `<section id="slug">` within the single document
|
|
45
|
+
- Sidebar links use `href="#slug"` anchors
|
|
46
|
+
- JavaScript shows/hides sections on hash change
|
|
47
|
+
- The sidebar hierarchy uses the same `buildSectionNav()` function as the static build, with a hash-link adapter: `makeHref = (urlPath) => '#' + slugify(urlPath)`
|
|
48
|
+
|
|
49
|
+
This ensures nav structure parity between `build` and `bundle` output.
|
|
50
|
+
|
|
51
|
+
### Raw Markdown
|
|
52
|
+
|
|
53
|
+
By default, raw `.md` source is embedded in the bundle as hidden `<script type="text/markdown">` blocks, accessible to AI agents. The `--no-raw` flag omits them to reduce file size.
|
|
54
|
+
|
|
55
|
+
### File Size
|
|
56
|
+
|
|
57
|
+
Typical documentation produces 100KB–1MB bundles. Image-heavy sites are larger due to base64 overhead (~33% per image). The tradeoff is acceptable because the primary use case is sharing, not serving at scale.
|
|
58
|
+
|
|
59
|
+
## Consequences
|
|
60
|
+
|
|
61
|
+
### Positive
|
|
62
|
+
|
|
63
|
+
- **Zero-infrastructure sharing**: Email, Slack, Google Drive — recipients open in any browser
|
|
64
|
+
- **Offline by default**: No network requests, no CDN dependencies
|
|
65
|
+
- **Point-in-time snapshot**: Bundle captures exact state of docs at build time
|
|
66
|
+
- **Same navigation as build**: `buildSectionNav()` shared between both output modes
|
|
67
|
+
- **AI-accessible**: Raw markdown available inside the bundle
|
|
68
|
+
|
|
69
|
+
### Negative
|
|
70
|
+
|
|
71
|
+
- Large bundles with many images (base64 adds ~33% overhead)
|
|
72
|
+
- No incremental loading — entire document loads at once
|
|
73
|
+
- Hash navigation doesn't support deep-linking from external URLs (fine for the sharing use case)
|
|
74
|
+
- Prism + Mermaid JS inlining adds ~500KB to every bundle
|
|
75
|
+
|
|
76
|
+
### Neutral
|
|
77
|
+
|
|
78
|
+
- Bundle and build share `collectFiles()`, `loadConfig()`, and `buildSectionNav()` from `shared.ts` — shared code stays in one place
|
|
79
|
+
- Bundle is a separate script (`scripts/bundle.ts`) rather than a mode flag on `scripts/build.ts`, keeping each focused
|
|
80
|
+
|
|
81
|
+
## Alternatives Considered
|
|
82
|
+
|
|
83
|
+
### PDF export
|
|
84
|
+
|
|
85
|
+
Widely shareable but loses interactivity (dark mode, collapsible nav, syntax highlighting themes). Would require a headless browser dependency (Puppeteer/Playwright). May be added later as a third output mode.
|
|
86
|
+
|
|
87
|
+
### MHTML / Web Archive
|
|
88
|
+
|
|
89
|
+
Browser-native single-file formats. Rejected because support is inconsistent (Safari doesn't support MHTML, Chrome's implementation has quirks) and generation requires browser automation.
|
|
90
|
+
|
|
91
|
+
### ZIP of static files
|
|
92
|
+
|
|
93
|
+
Solves the single-artifact problem but requires recipients to extract before viewing. Adds friction compared to double-clicking an HTML file.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "ADR-0004: Bun Runtime"
|
|
3
|
+
description: "Kitfly uses Bun as its runtime instead of Node.js"
|
|
4
|
+
author: "deliverylead"
|
|
5
|
+
supervised_by: "@3leapsdave"
|
|
6
|
+
date: "2026-02-09"
|
|
7
|
+
status: "accepted"
|
|
8
|
+
tags: ["adr", "runtime", "architecture", "tooling"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# ADR-0004: Bun Runtime
|
|
12
|
+
|
|
13
|
+
## Status
|
|
14
|
+
|
|
15
|
+
Accepted
|
|
16
|
+
|
|
17
|
+
## Context
|
|
18
|
+
|
|
19
|
+
Kitfly is a TypeScript CLI tool and static site generator. It needs a JavaScript runtime that can:
|
|
20
|
+
|
|
21
|
+
1. Execute TypeScript directly (no transpilation step)
|
|
22
|
+
2. Run fast — dev server startup, build times, and test execution should feel instant
|
|
23
|
+
3. Provide a built-in test runner (reduce dev dependencies)
|
|
24
|
+
4. Support the Node.js API surface used by kitfly (fs, path, http)
|
|
25
|
+
|
|
26
|
+
The project has a strict minimalism goal (ADR-0001): single production dependency (`marked`), minimal toolchain complexity.
|
|
27
|
+
|
|
28
|
+
## Decision
|
|
29
|
+
|
|
30
|
+
Use **Bun** as the primary runtime for development, testing, and production execution.
|
|
31
|
+
|
|
32
|
+
### What Bun Provides
|
|
33
|
+
|
|
34
|
+
| Capability | Replaces |
|
|
35
|
+
| --------------------------- | ---------------------------------------------------------- |
|
|
36
|
+
| Native TypeScript execution | `tsc` compilation step, `ts-node`, `tsx` |
|
|
37
|
+
| Built-in test runner | Separate test framework install (jest/mocha for execution) |
|
|
38
|
+
| Fast startup (~25ms) | Node.js cold start (~100-200ms) |
|
|
39
|
+
| Built-in package manager | npm/yarn/pnpm (for install speed) |
|
|
40
|
+
| `Bun.serve()` HTTP server | Express, Koa, or manual `http.createServer` |
|
|
41
|
+
|
|
42
|
+
### Runtime Boundary
|
|
43
|
+
|
|
44
|
+
Kitfly's source code uses standard Node.js APIs (`node:fs/promises`, `node:path`, `node:http`) rather than Bun-specific APIs where possible. The main Bun-specific usage is:
|
|
45
|
+
|
|
46
|
+
- `Bun.serve()` in the dev server (`scripts/dev.ts`)
|
|
47
|
+
- `bun run` as the script executor
|
|
48
|
+
- `bun test` via vitest (which uses Bun's runtime)
|
|
49
|
+
|
|
50
|
+
### User Requirement
|
|
51
|
+
|
|
52
|
+
Users must have Bun installed to run `kitfly`. This is documented in getting-started and enforced at CLI startup. Bun installation is a single command on all major platforms:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
curl -fsSL https://bun.sh/install | bash
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Test Runner
|
|
59
|
+
|
|
60
|
+
Tests use **vitest** running on the Bun runtime. This provides:
|
|
61
|
+
|
|
62
|
+
- vitest's assertion API and test organization
|
|
63
|
+
- Bun's fast execution speed
|
|
64
|
+
- Watch mode for development (`bun test:watch`)
|
|
65
|
+
|
|
66
|
+
## Consequences
|
|
67
|
+
|
|
68
|
+
### Positive
|
|
69
|
+
|
|
70
|
+
- **No build step**: TypeScript executes directly — `bun run src/cli.ts` just works
|
|
71
|
+
- **Fast iteration**: Dev server starts in under 100ms, full test suite runs in ~500ms (427 tests)
|
|
72
|
+
- **Fewer dependencies**: No need for `ts-node`, `tsx`, or a separate transpiler
|
|
73
|
+
- **Aligned with minimalism**: Bun's built-in capabilities reduce the toolchain surface
|
|
74
|
+
|
|
75
|
+
### Negative
|
|
76
|
+
|
|
77
|
+
- **Bun is a user prerequisite**: Users who only have Node.js installed need to install Bun first
|
|
78
|
+
- **Ecosystem maturity**: Bun is newer than Node.js — edge cases in compatibility exist (though kitfly's API surface is well-supported)
|
|
79
|
+
- **CI consideration**: CI environments need Bun installed (GitHub Actions: `oven-sh/setup-bun`)
|
|
80
|
+
|
|
81
|
+
### Neutral
|
|
82
|
+
|
|
83
|
+
- The standard Node.js API usage means a future port to Node.js (with a TypeScript loader) is feasible if needed
|
|
84
|
+
- Bun's package manager is used for `bun install` but `package.json` remains standard — compatible with npm/yarn if users prefer for dependency management
|
|
85
|
+
|
|
86
|
+
## Alternatives Considered
|
|
87
|
+
|
|
88
|
+
### Node.js + tsx
|
|
89
|
+
|
|
90
|
+
Node.js with `tsx` for TypeScript execution. Viable but slower startup, requires additional dev dependency, and doesn't provide a built-in test runner or fast HTTP server.
|
|
91
|
+
|
|
92
|
+
### Deno
|
|
93
|
+
|
|
94
|
+
Native TypeScript support and built-in tooling. Rejected because Deno's module resolution (URL imports, import maps) would complicate the project structure and `kitfly init` copy model. Bun's Node.js compatibility is more aligned with kitfly's design.
|
|
95
|
+
|
|
96
|
+
### Node.js + esbuild compilation
|
|
97
|
+
|
|
98
|
+
Compile TypeScript to JavaScript, ship compiled output. Rejected because it adds a build step to the development workflow and contradicts the "edit and run" simplicity goal.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "ADR-0005: Plugin Contract and Distribution Strategy"
|
|
3
|
+
description: "Defines plugin contract stability, versioning policy, and in-repo-first distribution with extraction path"
|
|
4
|
+
author: "devlead"
|
|
5
|
+
supervised_by: "@3leapsdave"
|
|
6
|
+
date: "2026-02-11"
|
|
7
|
+
status: "proposed"
|
|
8
|
+
tags: ["adr", "plugins", "architecture", "versioning", "supply-chain"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# ADR-0005: Plugin Contract and Distribution Strategy
|
|
12
|
+
|
|
13
|
+
## Status
|
|
14
|
+
|
|
15
|
+
Proposed
|
|
16
|
+
|
|
17
|
+
## Context
|
|
18
|
+
|
|
19
|
+
Kitfly v0.2.0 introduces optional plugin capabilities to support advanced use cases (starting with slides and live-slide extensions) without bloating core site code.
|
|
20
|
+
|
|
21
|
+
As of M1.1, basic slide **shape primitives** remain core CSS. Plugin scope starts at higher-level figures/widgets and engine integrations where deterministic core CSS stops.
|
|
22
|
+
|
|
23
|
+
Two operational choices must be explicit:
|
|
24
|
+
|
|
25
|
+
1. **Contract stability**: plugin authors and site operators need a clear, versioned interface that remains predictable.
|
|
26
|
+
2. **Repository strategy**: plugins can live in the main repo or a separate repo; we need a pragmatic default and a low-risk migration path.
|
|
27
|
+
|
|
28
|
+
## Decision
|
|
29
|
+
|
|
30
|
+
### 1. Treat plugin contract as versioned API
|
|
31
|
+
|
|
32
|
+
Kitfly will define a versioned plugin contract (`plugin.schema.json` + hook semantics) as a compatibility boundary.
|
|
33
|
+
|
|
34
|
+
Contract rules:
|
|
35
|
+
|
|
36
|
+
- Contract version is explicit (e.g. `contract: "1"`).
|
|
37
|
+
- Breaking changes require a new major contract version.
|
|
38
|
+
- Backward-compatible additions are allowed within a contract major version.
|
|
39
|
+
- Deprecations must include migration guidance before removal.
|
|
40
|
+
|
|
41
|
+
### 2. Start plugins in-repo for v0.2.0
|
|
42
|
+
|
|
43
|
+
For v0.2.0 delivery speed, first-party plugins are developed in the main kitfly repository under a dedicated plugin path and registry/config structure.
|
|
44
|
+
|
|
45
|
+
Why now:
|
|
46
|
+
|
|
47
|
+
- Faster iteration while contract and hooks are stabilizing.
|
|
48
|
+
- Lower coordination overhead across core + plugin changes.
|
|
49
|
+
- Simpler QA and dogfooding in a single branch/CI surface.
|
|
50
|
+
|
|
51
|
+
### 3. Keep extraction path explicit
|
|
52
|
+
|
|
53
|
+
In-repo is not permanent by requirement. Plugin layout, manifest format, and loader/registry interfaces must remain portable so plugins can move to `kitfly-plugins` later with minimal disruption.
|
|
54
|
+
|
|
55
|
+
Extraction trigger signals:
|
|
56
|
+
|
|
57
|
+
- plugin maintenance cadence diverges from core,
|
|
58
|
+
- external contribution volume rises,
|
|
59
|
+
- plugin release/security pipeline becomes materially heavier.
|
|
60
|
+
|
|
61
|
+
### 4. Security and policy baseline
|
|
62
|
+
|
|
63
|
+
Distribution policy applies regardless of repo location:
|
|
64
|
+
|
|
65
|
+
- version pinning required,
|
|
66
|
+
- checksum verification required,
|
|
67
|
+
- SRI required for CDN assets,
|
|
68
|
+
- untrusted third-party plugins denied by default unless explicit opt-in.
|
|
69
|
+
|
|
70
|
+
## Consequences
|
|
71
|
+
|
|
72
|
+
### Positive
|
|
73
|
+
|
|
74
|
+
- Contract clarity reduces integration breakage and support ambiguity.
|
|
75
|
+
- In-repo startup reduces delivery friction for v0.2.0.
|
|
76
|
+
- Future repo split remains available without contract rewrite.
|
|
77
|
+
|
|
78
|
+
### Negative
|
|
79
|
+
|
|
80
|
+
- Core repo grows in scope and review surface in the short term.
|
|
81
|
+
- Requires discipline to prevent plugin internals from leaking into core assumptions.
|
|
82
|
+
|
|
83
|
+
### Neutral
|
|
84
|
+
|
|
85
|
+
- Repo location is an implementation detail; contract/API stability is the true long-term commitment.
|
|
86
|
+
|
|
87
|
+
## Compatibility Policy (Initial)
|
|
88
|
+
|
|
89
|
+
- Contract v1 supported throughout v0.2.x.
|
|
90
|
+
- If contract v2 is introduced, v1 support remains for at least one minor release.
|
|
91
|
+
- Compatibility matrix (kitfly version ↔ contract version) must be documented in plugin docs.
|
|
92
|
+
|
|
93
|
+
## Alternatives Considered
|
|
94
|
+
|
|
95
|
+
### Separate plugin repo immediately
|
|
96
|
+
|
|
97
|
+
Pros: cleaner ownership and release boundaries from day one.
|
|
98
|
+
Cons: slower early iteration and more cross-repo coordination while contracts are still fluid.
|
|
99
|
+
|
|
100
|
+
Decision: defer split until signals justify it.
|
|
101
|
+
|
|
102
|
+
### No formal contract versioning
|
|
103
|
+
|
|
104
|
+
Rejected: too much ambiguity and high breakage risk once plugins exist in the wild.
|
|
105
|
+
|
|
106
|
+
## References
|
|
107
|
+
|
|
108
|
+
- [DDR-0005: Deterministic Layout Boundary](DDR-0005-deterministic-layout-boundary.md)
|
|
109
|
+
- [Design Catalog: Shapes and Figures](../../content/reference/design-catalog.md)
|
|
110
|
+
- [ADR-0001: Minimalist Site Code](ADR-0001-minimalist-site-code.md)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "DDR-0001: Viewport-Locked Layout with Fixed Footer Ribbon"
|
|
3
|
+
description: "Defines the kitfly page layout model: fixed chrome (header/footer) with scrollable middle band"
|
|
4
|
+
author: "uxdev"
|
|
5
|
+
supervised_by: "@3leapsdave"
|
|
6
|
+
date: "2026-02-06"
|
|
7
|
+
status: "accepted"
|
|
8
|
+
tags: ["ddr", "layout", "css", "ux"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# DDR-0001: Viewport-Locked Layout with Fixed Footer Ribbon
|
|
12
|
+
|
|
13
|
+
## Status
|
|
14
|
+
|
|
15
|
+
Accepted
|
|
16
|
+
|
|
17
|
+
## Context
|
|
18
|
+
|
|
19
|
+
Kitfly sites use a three-column layout: sidebar navigation, main content, and a table-of-contents panel. The original footer was appended to the content flow with `margin-left` to offset past the sidebar, which caused several problems:
|
|
20
|
+
|
|
21
|
+
- Footer only covered the content pane, not the full viewport width
|
|
22
|
+
- Sidebar navigation extended below the footer, breaking visual hierarchy
|
|
23
|
+
- Footer position depended on content length — short pages had it mid-screen, long pages required scrolling to find it
|
|
24
|
+
- On mobile the footer needed separate margin overrides per breakpoint
|
|
25
|
+
|
|
26
|
+
## Decision
|
|
27
|
+
|
|
28
|
+
Adopt a **viewport-locked layout** where fixed chrome (footer ribbon, and mobile header) occupies known height at viewport edges, and the middle band (sidebar + content + TOC) fills the remaining space between them.
|
|
29
|
+
|
|
30
|
+
### Layout Model
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
┌──────────────────────────────────────────────────┐
|
|
34
|
+
│ (mobile header — 768px and below only) │
|
|
35
|
+
├────────────┬─────────────────────────┬───────────┤
|
|
36
|
+
│ │ │ │
|
|
37
|
+
│ SIDEBAR │ CONTENT │ TOC │
|
|
38
|
+
│ fixed │ scrollable │ fixed │
|
|
39
|
+
│ left │ center │ right │
|
|
40
|
+
│ 280px │ flex: 1 │ 200px │
|
|
41
|
+
│ │ │ │
|
|
42
|
+
│ top: 0 │ margin-left: sidebar │ top: 6r │
|
|
43
|
+
│ bottom: │ padding-bottom: │ │
|
|
44
|
+
│ footer │ footer + 1rem │ │
|
|
45
|
+
│ │ │ │
|
|
46
|
+
├────────────┴─────────────────────────┴───────────┤
|
|
47
|
+
│ FOOTER RIBBON │
|
|
48
|
+
│ position: fixed; bottom: 0; left: 0; right: 0 │
|
|
49
|
+
│ height: var(--footer-height) z-index: 300 │
|
|
50
|
+
│ full-width — spans all columns │
|
|
51
|
+
└──────────────────────────────────────────────────┘
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### CSS Variables
|
|
55
|
+
|
|
56
|
+
| Variable | Value | Purpose |
|
|
57
|
+
| ----------------- | --------- | -------------------- |
|
|
58
|
+
| `--sidebar-width` | `280px` | Sidebar column width |
|
|
59
|
+
| `--footer-height` | `2.25rem` | Footer ribbon height |
|
|
60
|
+
|
|
61
|
+
### Z-Index Stack
|
|
62
|
+
|
|
63
|
+
| Layer | Z-Index | Element |
|
|
64
|
+
| -------------- | ------- | --------------------------- |
|
|
65
|
+
| Footer ribbon | 300 | `.site-footer` |
|
|
66
|
+
| Mobile header | 200 | `.mobile-header` |
|
|
67
|
+
| Mobile sidebar | 100 | `.sidebar` (mobile overlay) |
|
|
68
|
+
|
|
69
|
+
### Key Rules
|
|
70
|
+
|
|
71
|
+
1. **Footer is viewport-fixed**, not content-appended. It uses `position: fixed; bottom: 0` and spans full width.
|
|
72
|
+
2. **Sidebar stops above footer** via `bottom: var(--footer-height)` — no overlap, sidebar scrolls independently within its band.
|
|
73
|
+
3. **Content has bottom padding** of `calc(var(--footer-height) + 1rem)` so the last content line is never hidden behind the footer.
|
|
74
|
+
4. **Layout min-height** is `calc(100vh - var(--footer-height))` to prevent the document from extending behind the footer.
|
|
75
|
+
5. **Mobile breakpoints** inherit the same `--footer-height` variable — no per-breakpoint footer overrides needed.
|
|
76
|
+
6. **Print styles** hide the footer entirely (`.site-footer { display: none !important }`).
|
|
77
|
+
|
|
78
|
+
### Responsive Behavior
|
|
79
|
+
|
|
80
|
+
| Breakpoint | Sidebar | TOC | Footer |
|
|
81
|
+
| ---------- | ------------------ | ----------- | ------------------------ |
|
|
82
|
+
| > 1200px | Fixed left | Fixed right | Fixed bottom, full-width |
|
|
83
|
+
| 769–1200px | Fixed left (240px) | Hidden | Fixed bottom, full-width |
|
|
84
|
+
| ≤ 768px | Overlay (toggle) | Hidden | Fixed bottom, full-width |
|
|
85
|
+
|
|
86
|
+
The footer ribbon is consistent across all breakpoints — it never changes position or width.
|
|
87
|
+
|
|
88
|
+
## Consequences
|
|
89
|
+
|
|
90
|
+
### Positive
|
|
91
|
+
|
|
92
|
+
- Footer is always visible as a status/provenance ribbon without scrolling
|
|
93
|
+
- Sidebar navigation never extends below footer
|
|
94
|
+
- Single `--footer-height` variable controls all spacing — easy to adjust
|
|
95
|
+
- No per-breakpoint footer margin overrides
|
|
96
|
+
- Clean visual hierarchy: chrome frames content
|
|
97
|
+
|
|
98
|
+
### Negative
|
|
99
|
+
|
|
100
|
+
- Content needs `padding-bottom` to avoid being hidden — if `--footer-height` changes, padding must match (mitigated by using the CSS variable)
|
|
101
|
+
- Fixed footer consumes ~36px of viewport permanently — acceptable for the information density it provides (version, date, copyright, brand link)
|
|
102
|
+
|
|
103
|
+
## Alternatives Considered
|
|
104
|
+
|
|
105
|
+
### Sticky footer (content-appended)
|
|
106
|
+
|
|
107
|
+
The original approach. Footer stays in document flow but sticks to bottom on short pages. Rejected because it doesn't span the sidebar and creates layout inconsistencies across page lengths.
|
|
108
|
+
|
|
109
|
+
### CSS Grid viewport layout
|
|
110
|
+
|
|
111
|
+
Use `grid-template-rows: 1fr auto` on the body. Would work but requires restructuring the HTML template (moving sidebar inside a grid container). More invasive than necessary for the current fix.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "DDR-0002: Two-Layer Theme System"
|
|
3
|
+
description: "Defines the kitfly theming model: theme.yaml semantic tokens → generated CSS variables → styles.css fallbacks"
|
|
4
|
+
author: "deliverylead"
|
|
5
|
+
supervised_by: "@3leapsdave"
|
|
6
|
+
date: "2026-02-09"
|
|
7
|
+
status: "accepted"
|
|
8
|
+
tags: ["ddr", "theming", "css", "design"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# DDR-0002: Two-Layer Theme System
|
|
12
|
+
|
|
13
|
+
## Status
|
|
14
|
+
|
|
15
|
+
Accepted
|
|
16
|
+
|
|
17
|
+
## Context
|
|
18
|
+
|
|
19
|
+
Kitfly needs a theming system that lets users customize colors and typography without editing CSS. At the same time, the shipped CSS must render correctly even without a theme file — cold-start works must work. The system must support light/dark modes, syntax highlighting themes, and user-supplied theme files alongside bundled presets.
|
|
20
|
+
|
|
21
|
+
## Decision
|
|
22
|
+
|
|
23
|
+
Adopt a **two-layer theming model** where a YAML configuration layer defines semantic design tokens and a CSS layer consumes them as custom properties, with hardcoded fallbacks.
|
|
24
|
+
|
|
25
|
+
### Layer 1: theme.yaml → CSS Variables
|
|
26
|
+
|
|
27
|
+
`theme.yaml` defines semantic color tokens and typography settings:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
colors:
|
|
31
|
+
light:
|
|
32
|
+
background: "#ffffff"
|
|
33
|
+
surface: "#f5f7f8"
|
|
34
|
+
text: "#374151"
|
|
35
|
+
heading: "#152F46"
|
|
36
|
+
primary: "#007182"
|
|
37
|
+
accent: "#D17059"
|
|
38
|
+
border: "#e5e7eb"
|
|
39
|
+
dark:
|
|
40
|
+
background: "#0d1117"
|
|
41
|
+
surface: "#152F46"
|
|
42
|
+
# ...
|
|
43
|
+
|
|
44
|
+
typography:
|
|
45
|
+
body: "system"
|
|
46
|
+
headings: "system"
|
|
47
|
+
code: "mono"
|
|
48
|
+
baseSize: "16px"
|
|
49
|
+
scale: "1.25"
|
|
50
|
+
|
|
51
|
+
code:
|
|
52
|
+
light: "default"
|
|
53
|
+
dark: "okaidia"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`src/theme.ts` loads this file, deep-merges with `DEFAULT_THEME`, and calls `generateThemeCSS()` to produce a `<style id="kitfly-theme">` block that sets CSS custom properties on `:root`.
|
|
57
|
+
|
|
58
|
+
### Layer 2: styles.css Fallbacks
|
|
59
|
+
|
|
60
|
+
`src/site/styles.css` contains hardcoded fallback values in its `:root` block:
|
|
61
|
+
|
|
62
|
+
```css
|
|
63
|
+
:root {
|
|
64
|
+
--color-bg: #ffffff;
|
|
65
|
+
--color-bg-sidebar: #f8f9fa;
|
|
66
|
+
--color-text: #1a1a1a;
|
|
67
|
+
/* ... */
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
These fallbacks ensure the site renders correctly if `theme.yaml` is missing or `generateThemeCSS()` is not injected. When the theme `<style>` block is present, it overrides the fallbacks because it appears later in the document `<head>`.
|
|
72
|
+
|
|
73
|
+
### Token Mapping
|
|
74
|
+
|
|
75
|
+
| theme.yaml token | CSS variable | CSS usage |
|
|
76
|
+
| --------------------------- | -------------------- | ------------------------------- |
|
|
77
|
+
| `colors.light.background` | `--color-bg` | Page background |
|
|
78
|
+
| `colors.light.surface` | `--color-bg-sidebar` | Sidebar, code block backgrounds |
|
|
79
|
+
| `colors.light.text` | `--color-text` | Body text |
|
|
80
|
+
| `colors.light.textMuted` | `--color-text-muted` | Secondary text, metadata |
|
|
81
|
+
| `colors.light.heading` | `--color-accent` | Headings, logo color |
|
|
82
|
+
| `colors.light.primary` | `--color-link` | Links, active nav |
|
|
83
|
+
| `colors.light.primaryHover` | `--color-link-hover` | Link hover state |
|
|
84
|
+
| `colors.light.border` | `--color-border` | Borders, dividers |
|
|
85
|
+
|
|
86
|
+
Dark mode uses the same mapping under `@media (prefers-color-scheme: dark)` and `[data-theme="dark"]`.
|
|
87
|
+
|
|
88
|
+
### Dark Mode Strategy
|
|
89
|
+
|
|
90
|
+
Three selectors handle dark mode:
|
|
91
|
+
|
|
92
|
+
1. `@media (prefers-color-scheme: dark)` — OS-level automatic
|
|
93
|
+
2. `[data-theme="dark"]` — explicit user toggle
|
|
94
|
+
3. `:root:not([data-theme="light"])` — prevents OS dark overriding an explicit light choice
|
|
95
|
+
|
|
96
|
+
### Theme Presets
|
|
97
|
+
|
|
98
|
+
Bundled themes in `themes/` (`github.yaml`, `paper.yaml`, `terminal.yaml`) can be copied and customized. Users place their `theme.yaml` in the project root alongside `site.yaml`.
|
|
99
|
+
|
|
100
|
+
## Consequences
|
|
101
|
+
|
|
102
|
+
### Positive
|
|
103
|
+
|
|
104
|
+
- Users customize appearance via YAML without touching CSS
|
|
105
|
+
- CSS works standalone — no build step required to see something
|
|
106
|
+
- Dark mode works automatically via OS preference with manual override
|
|
107
|
+
- Theme presets provide starting points for customization
|
|
108
|
+
- Syntax highlighting themes are decoupled (Prism CDN URLs per light/dark)
|
|
109
|
+
|
|
110
|
+
### Negative
|
|
111
|
+
|
|
112
|
+
- CSS fallback values can drift from `DEFAULT_THEME` if one is updated without the other (mitigated: both live in the codebase and tests can catch drift)
|
|
113
|
+
- Token mapping is implicit — `surface` → `--color-bg-sidebar` isn't obvious without reading theme.ts
|
|
114
|
+
|
|
115
|
+
### Neutral
|
|
116
|
+
|
|
117
|
+
- Typography uses named presets (`system`, `serif`, `readable`) rather than raw font stacks — simple but limits advanced control
|
|
118
|
+
|
|
119
|
+
## Alternatives Considered
|
|
120
|
+
|
|
121
|
+
### CSS-only theming (no YAML)
|
|
122
|
+
|
|
123
|
+
Users edit CSS directly. Rejected because YAML is more accessible for non-developers and integrates with the existing `site.yaml` configuration model.
|
|
124
|
+
|
|
125
|
+
### CSS Modules / PostCSS pipeline
|
|
126
|
+
|
|
127
|
+
Build-time CSS transformation. Rejected because it contradicts ADR-0001 (minimalist site code) and adds build dependencies.
|
|
128
|
+
|
|
129
|
+
### Single source of truth (no CSS fallbacks)
|
|
130
|
+
|
|
131
|
+
Only generate CSS from theme.ts, no hardcoded `:root`. Rejected because it breaks cold-start: opening `styles.css` directly or loading before JS runs would show unstyled content.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "DDR-0003: Bounded Logo Slot"
|
|
3
|
+
description: "Logo rendering uses a bounded bounding-box model supporting both square icons and wide wordmarks"
|
|
4
|
+
author: "deliverylead"
|
|
5
|
+
supervised_by: "@3leapsdave"
|
|
6
|
+
date: "2026-02-09"
|
|
7
|
+
status: "accepted"
|
|
8
|
+
tags: ["ddr", "logo", "css", "branding"]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# DDR-0003: Bounded Logo Slot
|
|
12
|
+
|
|
13
|
+
## Status
|
|
14
|
+
|
|
15
|
+
Accepted
|
|
16
|
+
|
|
17
|
+
## Context
|
|
18
|
+
|
|
19
|
+
Kitfly sites display a brand logo in the sidebar header. Logos come in two aspect ratios:
|
|
20
|
+
|
|
21
|
+
- **Square icons** (1:1 or near-square) — app icons, monograms, favicons scaled up
|
|
22
|
+
- **Wide wordmarks** (3:1 or wider) — full brand names, logotypes with text
|
|
23
|
+
|
|
24
|
+
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.
|
|
25
|
+
|
|
26
|
+
## Decision
|
|
27
|
+
|
|
28
|
+
Use a **bounded bounding-box model** where the logo slot defines maximum dimensions per breakpoint, and the image fills the box while preserving its native aspect ratio.
|
|
29
|
+
|
|
30
|
+
### Slot Dimensions
|
|
31
|
+
|
|
32
|
+
| Breakpoint | Max Height | Max Width |
|
|
33
|
+
| ------------------ | ---------- | --------- |
|
|
34
|
+
| Desktop (> 1024px) | 64px | 180px |
|
|
35
|
+
| Tablet (≤ 1024px) | 56px | 150px |
|
|
36
|
+
| Mobile (≤ 768px) | 48px | 130px |
|
|
37
|
+
|
|
38
|
+
### CSS Implementation
|
|
39
|
+
|
|
40
|
+
```css
|
|
41
|
+
.logo-icon {
|
|
42
|
+
height: 64px;
|
|
43
|
+
width: auto;
|
|
44
|
+
max-width: 180px;
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The key properties:
|
|
49
|
+
|
|
50
|
+
- `height` sets the box height (the dominant constraint for square icons)
|
|
51
|
+
- `width: auto` preserves aspect ratio
|
|
52
|
+
- `max-width` prevents wide wordmarks from overflowing the sidebar
|
|
53
|
+
|
|
54
|
+
For wordmark logos, the `.logo-wordmark` class switches the constraint axis:
|
|
55
|
+
|
|
56
|
+
```css
|
|
57
|
+
.logo.logo-wordmark .logo-img {
|
|
58
|
+
max-width: 180px;
|
|
59
|
+
height: auto;
|
|
60
|
+
max-height: 64px;
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### logoType Configuration
|
|
65
|
+
|
|
66
|
+
`site.yaml` supports `brand.logoType` to select the rendering mode:
|
|
67
|
+
|
|
68
|
+
| Value | Behavior |
|
|
69
|
+
| ------------------ | ---------------------------------------------- |
|
|
70
|
+
| `"icon"` (default) | Height-dominant constraint, square/near-square |
|
|
71
|
+
| `"wordmark"` | Width-dominant constraint, wide aspect ratio |
|
|
72
|
+
|
|
73
|
+
The bundle system propagates `logoType` via `buildBundleSidebarHeader()` to ensure parity between build and bundle output.
|
|
74
|
+
|
|
75
|
+
### Supported Formats
|
|
76
|
+
|
|
77
|
+
- **PNG**: Recommended for icons. Use `kitfly-logo-128.png` at 128px for 2x retina clarity in the 64px slot.
|
|
78
|
+
- **SVG**: Supported but requires a tightly-cropped `viewBox`. An oversized canvas (e.g., A4 page `viewBox="0 0 210 297"`) will render the artwork too small within the bounded slot.
|
|
79
|
+
|
|
80
|
+
## Consequences
|
|
81
|
+
|
|
82
|
+
### Positive
|
|
83
|
+
|
|
84
|
+
- Both icon and wordmark logos render cleanly without CSS customization
|
|
85
|
+
- Responsive scaling is automatic — one set of breakpoints handles both shapes
|
|
86
|
+
- No logo distortion — aspect ratio is always preserved
|
|
87
|
+
- Bundle output matches static build (logoType propagation)
|
|
88
|
+
|
|
89
|
+
### Negative
|
|
90
|
+
|
|
91
|
+
- SVG logos with oversized viewBox render poorly — users must crop the viewBox to artwork bounds (documented in configuration reference)
|
|
92
|
+
- Two rendering modes (`icon` vs `wordmark`) add a configuration choice — mitigated by defaulting to `icon` which handles most cases
|
|
93
|
+
|
|
94
|
+
## Alternatives Considered
|
|
95
|
+
|
|
96
|
+
### Fixed pixel dimensions
|
|
97
|
+
|
|
98
|
+
Single `width: 120px; height: 40px` for all logos. Rejected because it distorts non-matching aspect ratios and doesn't adapt to breakpoints.
|
|
99
|
+
|
|
100
|
+
### Percentage-based sizing
|
|
101
|
+
|
|
102
|
+
`width: 60%` of sidebar. Rejected because it couples logo size to sidebar width and produces inconsistent results across breakpoints (280px desktop vs overlay mobile).
|
|
103
|
+
|
|
104
|
+
### User-specified dimensions in site.yaml
|
|
105
|
+
|
|
106
|
+
Let users set `logo.width` and `logo.height` in config. Rejected as over-engineering — the bounded box handles the common cases, and users can override via custom CSS if needed.
|