kitfly 0.2.1 → 0.2.3

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.
Files changed (108) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +25 -10
  3. package/VERSION +1 -1
  4. package/dist/_raw/content/guide/branding.md +146 -0
  5. package/dist/_raw/content/guide/data-driven-content.md +204 -0
  6. package/dist/_raw/content/reference/configuration.md +145 -7
  7. package/dist/_raw/content/reference/environment-variables.md +26 -1
  8. package/dist/_raw/content/reference/glossary.md +25 -1
  9. package/dist/_raw/content/reference/key-concepts.md +30 -2
  10. package/dist/_raw/content/reference/plugins.md +14 -0
  11. package/dist/_raw/docs/decisions/ADR-0006-data-driven-content.md +350 -0
  12. package/dist/content/deployment/preflight.html +10 -6
  13. package/dist/content/deployment/recipes/aws-s3.html +10 -6
  14. package/dist/content/deployment/recipes/cloudflare-pages.html +10 -6
  15. package/dist/content/deployment/recipes/cloudflare-r2.html +10 -6
  16. package/dist/content/deployment/recipes/fly-io.html +10 -6
  17. package/dist/content/deployment/recipes/github-pages.html +10 -6
  18. package/dist/content/deployment/recipes/netlify.html +10 -6
  19. package/dist/content/deployment/recipes/vercel.html +10 -6
  20. package/dist/content/deployment/secrets-and-env-vars.html +10 -6
  21. package/dist/content/deployment.html +10 -6
  22. package/dist/content/guide/approaches.html +10 -6
  23. package/dist/content/guide/branding.html +510 -0
  24. package/dist/content/guide/data-driven-content.html +543 -0
  25. package/dist/content/guide/features.html +10 -6
  26. package/dist/content/guide/getting-started.html +10 -6
  27. package/dist/content/guide/kitfly-overview.html +10 -6
  28. package/dist/content/reference/configuration.html +135 -9
  29. package/dist/content/reference/design-catalog.html +10 -6
  30. package/dist/content/reference/environment-variables.html +50 -8
  31. package/dist/content/reference/glossary.html +24 -8
  32. package/dist/content/reference/key-concepts.html +33 -9
  33. package/dist/content/reference/plugins.html +22 -7
  34. package/dist/content/reference/slides-authoring-guidelines.html +10 -6
  35. package/dist/content/reference/structure.html +10 -6
  36. package/dist/content/reference.html +10 -6
  37. package/dist/content/templates/crucible.html +10 -6
  38. package/dist/content/templates/handbook.html +10 -6
  39. package/dist/content/templates/minimal.html +10 -6
  40. package/dist/content/templates/overview.html +10 -6
  41. package/dist/content/templates/pipeline.html +10 -6
  42. package/dist/content/templates/productbook.html +10 -6
  43. package/dist/content/templates/runbook.html +10 -6
  44. package/dist/content/templates/servicebook.html +10 -6
  45. package/dist/content-index.json +29 -2
  46. package/dist/docs/decisions/ADR-0001-minimalist-site-code.html +10 -6
  47. package/dist/docs/decisions/ADR-0002-ai-accessibility.html +10 -6
  48. package/dist/docs/decisions/ADR-0003-single-file-bundle.html +10 -6
  49. package/dist/docs/decisions/ADR-0004-bun-runtime.html +10 -6
  50. package/dist/docs/decisions/ADR-0005-plugin-contract-and-distribution.html +10 -6
  51. package/dist/docs/decisions/ADR-0006-data-driven-content.html +752 -0
  52. package/dist/docs/decisions/DDR-0001-viewport-locked-layout.html +10 -6
  53. package/dist/docs/decisions/DDR-0002-theme-system.html +10 -6
  54. package/dist/docs/decisions/DDR-0003-bounded-logo-slot.html +10 -6
  55. package/dist/docs/decisions/DDR-0004-slides-rendering-model.html +10 -6
  56. package/dist/docs/decisions/DDR-0005-deterministic-layout-boundary.html +10 -6
  57. package/dist/docs/userguide/cli/build.html +10 -6
  58. package/dist/docs/userguide/cli/bundle.html +10 -6
  59. package/dist/docs/userguide/cli/dev.html +10 -6
  60. package/dist/docs/userguide/cli/init.html +10 -6
  61. package/dist/docs/userguide/cli/servers.html +10 -6
  62. package/dist/docs/userguide/cli/stop.html +10 -6
  63. package/dist/docs/userguide/cli/update.html +10 -6
  64. package/dist/docs/userguide/cli/version.html +10 -6
  65. package/dist/docs/userguide/cli.html +10 -6
  66. package/dist/docs/userguide/sharing.html +10 -6
  67. package/dist/index.html +10 -6
  68. package/dist/llms.txt +3 -3
  69. package/dist/provenance.json +4 -4
  70. package/dist/schemas/plugin-registry.schema.html +10 -6
  71. package/dist/schemas/plugin-schemas-notes.html +10 -6
  72. package/dist/schemas/plugin.schema.html +10 -6
  73. package/dist/schemas/plugins.schema.html +10 -6
  74. package/dist/schemas/v0/common.schema.html +14 -10
  75. package/dist/schemas/v0/plugin-registry.schema.html +13 -9
  76. package/dist/schemas/v0/plugin.schema.html +13 -9
  77. package/dist/schemas/v0/plugins.schema.html +13 -9
  78. package/dist/schemas/v0/site.schema.html +67 -7
  79. package/dist/schemas/v0/theme.schema.html +21 -17
  80. package/dist/schemas.html +10 -6
  81. package/dist/styles.css +39 -4
  82. package/package.json +1 -1
  83. package/plugins-dist/latex-runtime.js +140 -0
  84. package/plugins-dist/latex.js +178 -0
  85. package/plugins-dist/slides-charts-lite-runtime.js +179 -0
  86. package/plugins-dist/slides-charts-lite.js +198 -0
  87. package/registry/plugins.yaml +25 -0
  88. package/schemas/v0/site.schema.json +56 -0
  89. package/scripts/build.ts +191 -69
  90. package/scripts/bundle.ts +118 -10
  91. package/scripts/dev.ts +245 -166
  92. package/src/__tests__/brief.test.ts +151 -0
  93. package/src/__tests__/build.test.ts +169 -1
  94. package/src/__tests__/bundle.test.ts +134 -0
  95. package/src/__tests__/init.test.ts +51 -2
  96. package/src/__tests__/latex-runtime.bun.test.ts +35 -0
  97. package/src/__tests__/shared.test.ts +598 -1
  98. package/src/__tests__/slides-charts-lite-runtime.bun.test.ts +45 -0
  99. package/src/cli.ts +11 -4
  100. package/src/commands/init.ts +1 -1
  101. package/src/shared.ts +725 -18
  102. package/src/site/styles.css +39 -4
  103. package/src/site/template.html +5 -2
  104. package/src/templates/brief.ts +486 -0
  105. package/src/templates/deck.ts +59 -0
  106. package/src/templates/driver.ts +46 -13
  107. package/src/templates/handbook.ts +32 -0
  108. package/src/templates/runbook.ts +32 -0
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "Configuration"
3
3
  description: "Customize your kitfly site"
4
- last_updated: "2026-02-03"
4
+ last_updated: "2026-02-17"
5
5
  ---
6
6
 
7
7
  # Configuration
@@ -59,6 +59,18 @@ docroot: "content"
59
59
 
60
60
  See [Folder Structure](structure.html) for details.
61
61
 
62
+ ### dataroot (v0.2.3+)
63
+
64
+ Data directory used for frontmatter `data:` bindings.
65
+
66
+ ```yaml
67
+ dataroot: "data"
68
+ ```
69
+
70
+ Default: `data`
71
+
72
+ `dataroot` must resolve inside the site root (no `../`, no absolute paths). Data files are loaded at build time and are not copied into output pages.
73
+
62
74
  ### title
63
75
 
64
76
  Site title. Appears in browser tab and header.
@@ -100,10 +112,13 @@ brand:
100
112
  name: "My Project" # Text in header
101
113
  url: "/" # Logo link
102
114
  logo: "assets/brand/my-logo.png" # Sidebar logo image
115
+ logoDark: "assets/brand/my-logo-dark.png" # Dark mode logo (optional)
103
116
  favicon: "assets/brand/favicon-32.png" # Browser tab icon
104
117
  external: true # Open in new tab (optional)
105
118
  ```
106
119
 
120
+ When `logoDark` is set, kitfly shows it in dark mode instead of applying the default brightness filter. See the [Branding](/content/guide/branding) guide for details on dark mode variants.
121
+
107
122
  The logo renders inside a bounded slot that preserves aspect ratio:
108
123
 
109
124
  | Breakpoint | Max Height | Max Width |
@@ -139,7 +154,7 @@ sections:
139
154
  | ---------- | ------- | ----- | ------------------------------------------------- |
140
155
  | `maxDepth` | 4 | 1–10 | How many directory levels to scan for `.md` files |
141
156
 
142
- Deeper sections produce hierarchical sidebar navigation with collapsible groups. Set a lower `maxDepth` for sections where you want a flatter sidebar.
157
+ Deeper sections produce hierarchical sidebar navigation with collapsible groups. This applies to both docs and slides modes — slide decks with subfolder content get nested, collapsible nav while keeping `#slide-N` hash navigation. Set a lower `maxDepth` for sections where you want a flatter sidebar.
143
158
 
144
159
  **Explicit files:** For precise control over which files appear (bypasses auto-discovery):
145
160
 
@@ -150,6 +165,51 @@ sections:
150
165
  files: ["README.md", "CHANGELOG.md"]
151
166
  ```
152
167
 
168
+ ### profiles (v0.2.3+)
169
+
170
+ Named content profiles for single-source multi-audience filtering.
171
+
172
+ ```yaml
173
+ profiles:
174
+ alpha:
175
+ description: "Includes alpha-tagged content"
176
+ include:
177
+ tags: ["alpha"]
178
+ beta:
179
+ description: "Includes beta-tagged content"
180
+ include:
181
+ tags: ["beta"]
182
+ ```
183
+
184
+ Activate a profile via CLI flag or environment variable:
185
+
186
+ ```bash
187
+ kitfly dev ./mysite --profile alpha
188
+ KITFLY_PROFILE=beta kitfly build ./mysite
189
+ ```
190
+
191
+ Files with a matching `profile:` frontmatter tag are included. Files without a `profile:` field are always included. Tagged files are excluded when no profile is active or when the active profile doesn't match.
192
+
193
+ Sites without `profiles:` in site.yaml are completely unaffected — adding the field has no effect until a profile is explicitly activated.
194
+
195
+ ### prebuild (v0.2.3+)
196
+
197
+ Run generator commands before `dev`, `build`, and `bundle`.
198
+
199
+ ```yaml
200
+ prebuild:
201
+ - command: "bun run scripts/generate-pricing-data.ts"
202
+ watch: ["data/raw/pricing-input.json"]
203
+ - command: "bun run scripts/generate-team-data.ts"
204
+ ```
205
+
206
+ Rules:
207
+
208
+ - Hooks run sequentially in declared order.
209
+ - Non-zero exit halts the command with hook stderr.
210
+ - In dev mode, `watch:` patterns re-run matching hooks on file changes.
211
+ - Kitfly sets `KITFLY_SITE_ROOT`, `KITFLY_DATA_DIR`, `KITFLY_BUILD_MODE`, and `KITFLY_PROFILE` (when active).
212
+
153
213
  ### footer
154
214
 
155
215
  Footer has three zones: provenance (left), copyright and links (center), and Kitfly attribution (right). Each field is independent — setting one does not affect the others.
@@ -165,6 +225,11 @@ v0.1.1 · Published 2026-02-10 © 2026 Acme Inc. · acme.com Built with
165
225
  | `copyrightUrl` | _(none)_ | Makes the copyright text a clickable link |
166
226
  | `links` | Your `brand.url` shown as a link | Links after the copyright text (max 10) |
167
227
  | `attribution` | `true` | "Built with Kitfly" on the right |
228
+ | `logo` | _(none)_ | Image logo in the footer-left position |
229
+ | `logoDark` | _(none)_ | Dark mode variant of the footer logo |
230
+ | `logoUrl` | _(none)_ | Makes the footer logo a clickable link |
231
+ | `logoAlt` | Copyright text or brand name | Alt text for the footer logo |
232
+ | `logoHeight` | `20` | Max height of footer logo in pixels |
168
233
 
169
234
  **Common case: product name differs from copyright holder.** The default copyright uses `brand.name`, which is your product title (shown in the header). If your legal entity is different, override it:
170
235
 
@@ -205,6 +270,19 @@ When `links` is set, it replaces the default brand URL link. When `links` is omi
205
270
 
206
271
  Set `footer.attribution: false` to remove the "Built with Kitfly" text from the footer entirely.
207
272
 
273
+ **Footer logo** — add an image to the footer ribbon (e.g. a parent company logo):
274
+
275
+ ```yaml
276
+ footer:
277
+ logo: "assets/brand/footer-logo.png"
278
+ logoDark: "assets/brand/footer-logo-dark.png"
279
+ logoUrl: "https://example.com"
280
+ logoAlt: "Example Corp"
281
+ logoHeight: 24
282
+ ```
283
+
284
+ The footer logo renders at the leading edge of the ribbon, before provenance info. All footer logo fields are optional — if `logo` is omitted, the footer renders as text only. See the [Branding](/content/guide/branding) guide for full details.
285
+
208
286
  ### theme layout (`theme.yaml`)
209
287
 
210
288
  `theme.yaml` can override layout variables, including sidebar width.
@@ -232,11 +310,71 @@ last_updated: "2026-02-03"
232
310
  # Content starts here
233
311
  ```
234
312
 
235
- | Field | Purpose |
236
- | -------------- | ------------------------------- |
237
- | `title` | Page title (overrides filename) |
238
- | `description` | Meta description |
239
- | `last_updated` | Shown in page footer |
313
+ | Field | Purpose |
314
+ | -------------- | ------------------------------------------------------------------- |
315
+ | `title` | Page title (overrides filename) |
316
+ | `description` | Meta description |
317
+ | `last_updated` | Shown in page footer |
318
+ | `data` | Data file for `{{ key }}` / `{{ snippet:name }}` bindings (v0.2.3+) |
319
+ | `profile` | Profile tag(s) for audience filtering (v0.2.3+) |
320
+
321
+ ### `data` frontmatter (v0.2.3+)
322
+
323
+ Bind a page to a data file for value substitution and snippet injection:
324
+
325
+ ```yaml
326
+ ---
327
+ title: "Pricing"
328
+ data: "data/pricing.yaml"
329
+ ---
330
+ ```
331
+
332
+ The `data:` path is relative to site root. The data file uses a structured format:
333
+
334
+ ```yaml
335
+ globals:
336
+ company: "Acme Corp"
337
+ baseline_rate: "200"
338
+
339
+ pages:
340
+ - path: content/product/pricing.md
341
+ inject:
342
+ hero: "Implementation and operating costs"
343
+ snippets:
344
+ - slot: pricing-table
345
+ content: |
346
+ | Tier | Price |
347
+ |------|-------|
348
+ | Basic | $10/mo |
349
+ ```
350
+
351
+ **Path convention:** `pages[].path` must be relative to site root including the `content/` prefix — e.g. `content/product/pricing.md`, not `product/pricing.md`.
352
+
353
+ In the markdown body, use `{{ key }}` for value substitution and `{{ snippet:name }}` for block injection. Formatters apply with pipe syntax: `{{ baseline_rate | dollar }}`. See the [Data-Driven Content](/content/guide/data-driven-content) guide for the full formatter reference and generator patterns.
354
+
355
+ Pages without `data:` frontmatter are completely unaffected — literal `{{ }}` text passes through as-is.
356
+
357
+ ### `profile` frontmatter (v0.2.3+)
358
+
359
+ Tag a file for profile-based filtering:
360
+
361
+ ```yaml
362
+ ---
363
+ title: "Engagement Timeline"
364
+ profile: alpha
365
+ ---
366
+ ```
367
+
368
+ Multiple profiles:
369
+
370
+ ```yaml
371
+ ---
372
+ title: "Shared Appendix"
373
+ profile: [alpha, beta]
374
+ ---
375
+ ```
376
+
377
+ Files without a `profile:` field are always included regardless of which profile is active. See `profiles` in Settings above.
240
378
 
241
379
  ## No Configuration
242
380
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "Environment Variables"
3
3
  description: "A beginner-friendly primer (with copy-paste examples)"
4
- last_updated: "2026-02-12"
4
+ last_updated: "2026-02-17"
5
5
  ---
6
6
 
7
7
  # Environment Variables
@@ -58,6 +58,31 @@ If you use one:
58
58
  - make sure it is gitignored
59
59
  - consider adding a `.env.example` with placeholder values (safe to commit)
60
60
 
61
+ ## Kitfly environment variables (v0.2.3+)
62
+
63
+ ### `KITFLY_PROFILE`
64
+
65
+ Activate a content profile without the `--profile` CLI flag:
66
+
67
+ ```bash
68
+ KITFLY_PROFILE=alpha kitfly build ./mysite
69
+ ```
70
+
71
+ Equivalent to `kitfly build ./mysite --profile alpha`.
72
+
73
+ ### Pre-build hook variables
74
+
75
+ Kitfly sets these before running each `prebuild:` hook:
76
+
77
+ | Variable | Value | Example |
78
+ | ------------------- | ------------------------------- | --------------------------- |
79
+ | `KITFLY_SITE_ROOT` | Absolute path to kitsite root | `/Users/me/my-docs` |
80
+ | `KITFLY_DATA_DIR` | Data directory relative to root | `data/` |
81
+ | `KITFLY_BUILD_MODE` | Current build mode | `dev`, `build`, or `bundle` |
82
+ | `KITFLY_PROFILE` | Active content profile (if any) | `alpha` |
83
+
84
+ These allow generators to adapt behavior per build context — for example, a generator might skip expensive API calls in `dev` mode or produce different output per profile.
85
+
61
86
  ## Quick troubleshooting
62
87
 
63
88
  - If a command says a variable is missing, print it:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "Glossary"
3
3
  description: "Quick definitions for common Kitfly terms"
4
- last_updated: "2026-02-12"
4
+ last_updated: "2026-02-17"
5
5
  ---
6
6
 
7
7
  # Glossary
@@ -90,3 +90,27 @@ A named value provided to commands and apps by your shell or host platform (ofte
90
90
  ## Secret
91
91
 
92
92
  A sensitive value (token/key/password) that should not be committed to git and should be stored in a secret manager or environment variable.
93
+
94
+ ## Profile
95
+
96
+ A named content filter activated via `--profile` or `KITFLY_PROFILE`. Files tagged with `profile:` in frontmatter are only included when their profile is active. Enables single-source multi-audience workflows.
97
+
98
+ ## Kitsite
99
+
100
+ The workspace Kitfly renders: typically contains `site.yaml`, content files, and optional `data/` + `scripts/`.
101
+
102
+ ## Generator
103
+
104
+ A script that transforms external data into Kitfly’s file contract (usually writes `data/*.yaml` or `data/*.json`).
105
+
106
+ ## Data binding
107
+
108
+ Build-time substitution from a bound data file into markdown (`{{ key }}` and `{{ snippet:name }}`).
109
+
110
+ ## Formatter
111
+
112
+ A deterministic value transform in bindings (for example `dollar`, `number`, `percent`, `round(n)`, `upper`, `lower`).
113
+
114
+ ## Snippet
115
+
116
+ A named markdown block in a data file that can be injected with `{{ snippet:name }}`.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "Key Concepts"
3
3
  description: "Mental models for how Kitfly works"
4
- last_updated: "2026-02-12"
4
+ last_updated: "2026-02-17"
5
5
  ---
6
6
 
7
7
  # Key Concepts
@@ -86,7 +86,7 @@ If you do: `theme.yaml` is your main “make it mine” knob.
86
86
  Kitfly can render the same Markdown content in two layouts:
87
87
 
88
88
  - **docs** (default): scrolling pages optimized for reading
89
- - **slides**: fixed-aspect one page at a time slides with keyboard navigation
89
+ - **slides**: fixed-aspect "one page at a time" slides with keyboard navigation
90
90
 
91
91
  Slides mode is configured in `site.yaml`:
92
92
 
@@ -95,12 +95,40 @@ mode: slides
95
95
  aspect: "16/9"
96
96
  ```
97
97
 
98
+ In both modes, organizing content into subfolders produces hierarchical sidebar navigation with collapsible groups. In slides mode, the nav links remain `#slide-N` hash anchors — the tree structure is visual grouping only.
99
+
98
100
  ## Assets
99
101
 
100
102
  Kitfly will serve and bundle common “content-adjacent” assets referenced from Markdown, like images and PDFs.
101
103
 
102
104
  Rule of thumb: if it lives next to your docs, Kitfly tries to do the right thing.
103
105
 
106
+ ## Content profiles (v0.2.3+)
107
+
108
+ Profiles let you produce multiple audience-specific outputs from a single kitsite. Tag files with `profile:` in frontmatter and activate a profile via `--profile` flag or `KITFLY_PROFILE` env var.
109
+
110
+ - Files without `profile:` are always included (the common case).
111
+ - Tagged files only appear when their profile is active.
112
+ - No active profile = only untagged content.
113
+
114
+ This is a startup parameter, not a runtime toggle — changing profiles requires restarting the dev server.
115
+
116
+ ## Data bindings (v0.2.3+)
117
+
118
+ A page can opt into build-time bindings by setting `data:` in frontmatter.
119
+
120
+ - `{{ key }}` resolves scalar values from a data file.
121
+ - `{{ snippet:name }}` injects a named markdown block.
122
+ - Formatters like `dollar`, `number`, `percent`, `round(n)`, `upper`, `lower` apply with pipe syntax.
123
+
124
+ No loops/conditionals are supported in bindings. If you need logic, use a generator script and write data files before render.
125
+
126
+ ## Pre-build hooks (v0.2.3+)
127
+
128
+ `prebuild:` commands in `site.yaml` run before `dev`, `build`, and `bundle`.
129
+
130
+ Use hooks for generators (CSV/API/etc. to `data/*.yaml` or `data/*.json`). In dev mode, hook `watch:` patterns can re-run hooks when source files change.
131
+
104
132
  ## Provenance
105
133
 
106
134
  Kitfly can emit provenance information (version/build date/git info) so you can answer “what did we ship?”.
@@ -26,6 +26,20 @@ plugins:
26
26
 
27
27
  Canonical plugins are referenced as pinned strings: `name@x.y.z`.
28
28
 
29
+ ### Canonical plugins (v0.2.2)
30
+
31
+ - `callouts@0.2.0` - styled NOTE/TIP/INFO/WARNING/DANGER blockquotes
32
+ - `slides-visuals@0.2.1` - slide widgets + figures via `:::` blocks (`slides` mode only)
33
+ - `latex@0.2.2` - KaTeX math rendering for `$...$`, `$$...$$`, and fenced `math` blocks
34
+ - `slides-charts-lite@0.2.2` - bar/line/pie charts from fenced `chart` blocks (`slides` mode only)
35
+
36
+ Example:
37
+
38
+ ```yaml
39
+ plugins:
40
+ - latex@0.2.2
41
+ ```
42
+
29
43
  ## Registry + assets
30
44
 
31
45
  Canonical plugins come from a registry file: