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.
Files changed (209) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +63 -16
  3. package/VERSION +1 -1
  4. package/dist/_raw/content/deployment/preflight.md +134 -0
  5. package/dist/_raw/content/deployment/recipes/aws-s3.md +128 -0
  6. package/dist/_raw/content/deployment/recipes/cloudflare-pages.md +73 -0
  7. package/dist/_raw/content/deployment/recipes/cloudflare-r2.md +156 -0
  8. package/dist/_raw/content/deployment/recipes/fly-io.md +57 -0
  9. package/dist/_raw/content/deployment/recipes/github-pages.md +112 -0
  10. package/dist/_raw/content/deployment/recipes/netlify.md +99 -0
  11. package/dist/_raw/content/deployment/recipes/vercel.md +88 -0
  12. package/dist/_raw/content/deployment/secrets-and-env-vars.md +75 -0
  13. package/dist/_raw/content/deployment.md +128 -0
  14. package/dist/_raw/content/guide/approaches.md +182 -0
  15. package/dist/_raw/content/guide/features.md +121 -0
  16. package/dist/_raw/content/guide/getting-started.md +112 -0
  17. package/dist/_raw/content/guide/kitfly-overview.md +209 -0
  18. package/dist/_raw/content/reference/configuration.md +259 -0
  19. package/dist/_raw/content/reference/design-catalog.md +167 -0
  20. package/dist/_raw/content/reference/environment-variables.md +66 -0
  21. package/dist/_raw/content/reference/glossary.md +92 -0
  22. package/dist/_raw/content/reference/key-concepts.md +118 -0
  23. package/dist/_raw/content/reference/plugins.md +220 -0
  24. package/dist/_raw/content/reference/slides-authoring-guidelines.md +129 -0
  25. package/dist/_raw/content/reference/structure.md +166 -0
  26. package/dist/_raw/content/reference.md +20 -0
  27. package/dist/_raw/content/templates/crucible.md +192 -0
  28. package/dist/_raw/content/templates/handbook.md +83 -0
  29. package/dist/_raw/content/templates/minimal.md +138 -0
  30. package/dist/_raw/content/templates/overview.md +187 -0
  31. package/dist/_raw/content/templates/pipeline.md +151 -0
  32. package/dist/_raw/content/templates/productbook.md +187 -0
  33. package/dist/_raw/content/templates/runbook.md +193 -0
  34. package/dist/_raw/content/templates/servicebook.md +163 -0
  35. package/dist/_raw/docs/decisions/ADR-0001-minimalist-site-code.md +118 -0
  36. package/dist/_raw/docs/decisions/ADR-0002-ai-accessibility.md +153 -0
  37. package/dist/_raw/docs/decisions/ADR-0003-single-file-bundle.md +93 -0
  38. package/dist/_raw/docs/decisions/ADR-0004-bun-runtime.md +98 -0
  39. package/dist/_raw/docs/decisions/ADR-0005-plugin-contract-and-distribution.md +110 -0
  40. package/dist/_raw/docs/decisions/DDR-0001-viewport-locked-layout.md +111 -0
  41. package/dist/_raw/docs/decisions/DDR-0002-theme-system.md +131 -0
  42. package/dist/_raw/docs/decisions/DDR-0003-bounded-logo-slot.md +106 -0
  43. package/dist/_raw/docs/decisions/DDR-0004-slides-rendering-model.md +113 -0
  44. package/dist/_raw/docs/decisions/DDR-0005-deterministic-layout-boundary.md +107 -0
  45. package/dist/_raw/docs/userguide/cli/build.md +85 -0
  46. package/dist/_raw/docs/userguide/cli/bundle.md +81 -0
  47. package/dist/_raw/docs/userguide/cli/dev.md +92 -0
  48. package/dist/_raw/docs/userguide/cli/init.md +116 -0
  49. package/dist/_raw/docs/userguide/cli/servers.md +69 -0
  50. package/dist/_raw/docs/userguide/cli/stop.md +76 -0
  51. package/dist/_raw/docs/userguide/cli/update.md +78 -0
  52. package/dist/_raw/docs/userguide/cli/version.md +65 -0
  53. package/dist/_raw/docs/userguide/cli.md +34 -0
  54. package/dist/_raw/docs/userguide/sharing.md +94 -0
  55. package/dist/_raw/schemas/plugin-schemas-notes.md +71 -0
  56. package/dist/_raw/schemas.md +42 -0
  57. package/dist/assets/brand/kitfly-favicon-32.png +0 -0
  58. package/dist/assets/brand/kitfly-icon-64.png +0 -0
  59. package/dist/assets/brand/kitfly-logo-128.png +0 -0
  60. package/dist/assets/brand/kitfly-logo-512.png +0 -0
  61. package/dist/assets/brand/kitfly-logo.svg +12132 -0
  62. package/dist/assets/brand/kitfly-neon-128.png +0 -0
  63. package/dist/assets/brand/kitfly-neon-192.png +0 -0
  64. package/dist/assets/brand/kitfly-neon-256.png +0 -0
  65. package/dist/assets/brand/kitfly-neon.png +0 -0
  66. package/dist/assets/brand/palette.md +75 -0
  67. package/dist/content/deployment/index.html +11 -0
  68. package/dist/content/deployment/preflight.html +418 -0
  69. package/dist/content/deployment/recipes/aws-s3.html +421 -0
  70. package/dist/content/deployment/recipes/cloudflare-pages.html +372 -0
  71. package/dist/content/deployment/recipes/cloudflare-r2.html +443 -0
  72. package/dist/content/deployment/recipes/fly-io.html +356 -0
  73. package/dist/content/deployment/recipes/github-pages.html +414 -0
  74. package/dist/content/deployment/recipes/index.html +11 -0
  75. package/dist/content/deployment/recipes/netlify.html +394 -0
  76. package/dist/content/deployment/recipes/vercel.html +382 -0
  77. package/dist/content/deployment/secrets-and-env-vars.html +380 -0
  78. package/dist/content/deployment.html +426 -0
  79. package/dist/content/guide/approaches.html +501 -0
  80. package/dist/content/guide/features.html +436 -0
  81. package/dist/content/guide/getting-started.html +403 -0
  82. package/dist/content/guide/index.html +11 -0
  83. package/dist/content/guide/kitfly-overview.html +544 -0
  84. package/dist/content/index.html +11 -0
  85. package/dist/content/reference/configuration.html +580 -0
  86. package/dist/content/reference/design-catalog.html +449 -0
  87. package/dist/content/reference/environment-variables.html +367 -0
  88. package/dist/content/reference/glossary.html +368 -0
  89. package/dist/content/reference/index.html +11 -0
  90. package/dist/content/reference/key-concepts.html +399 -0
  91. package/dist/content/reference/plugins.html +491 -0
  92. package/dist/content/reference/slides-authoring-guidelines.html +418 -0
  93. package/dist/content/reference/structure.html +463 -0
  94. package/dist/content/reference.html +335 -0
  95. package/dist/content/templates/crucible.html +546 -0
  96. package/dist/content/templates/handbook.html +405 -0
  97. package/dist/content/templates/index.html +11 -0
  98. package/dist/content/templates/minimal.html +447 -0
  99. package/dist/content/templates/overview.html +558 -0
  100. package/dist/content/templates/pipeline.html +494 -0
  101. package/dist/content/templates/productbook.html +540 -0
  102. package/dist/content/templates/runbook.html +543 -0
  103. package/dist/content/templates/servicebook.html +523 -0
  104. package/dist/content-index.json +549 -0
  105. package/dist/docs/decisions/ADR-0001-minimalist-site-code.html +491 -0
  106. package/dist/docs/decisions/ADR-0002-ai-accessibility.html +434 -0
  107. package/dist/docs/decisions/ADR-0003-single-file-bundle.html +412 -0
  108. package/dist/docs/decisions/ADR-0004-bun-runtime.html +409 -0
  109. package/dist/docs/decisions/ADR-0005-plugin-contract-and-distribution.html +402 -0
  110. package/dist/docs/decisions/DDR-0001-viewport-locked-layout.html +459 -0
  111. package/dist/docs/decisions/DDR-0002-theme-system.html +452 -0
  112. package/dist/docs/decisions/DDR-0003-bounded-logo-slot.html +423 -0
  113. package/dist/docs/decisions/DDR-0004-slides-rendering-model.html +399 -0
  114. package/dist/docs/decisions/DDR-0005-deterministic-layout-boundary.html +422 -0
  115. package/dist/docs/decisions/index.html +11 -0
  116. package/dist/docs/userguide/cli/build.html +408 -0
  117. package/dist/docs/userguide/cli/bundle.html +419 -0
  118. package/dist/docs/userguide/cli/dev.html +428 -0
  119. package/dist/docs/userguide/cli/index.html +11 -0
  120. package/dist/docs/userguide/cli/init.html +436 -0
  121. package/dist/docs/userguide/cli/servers.html +393 -0
  122. package/dist/docs/userguide/cli/stop.html +408 -0
  123. package/dist/docs/userguide/cli/update.html +406 -0
  124. package/dist/docs/userguide/cli/version.html +406 -0
  125. package/dist/docs/userguide/cli.html +386 -0
  126. package/dist/docs/userguide/index.html +11 -0
  127. package/dist/docs/userguide/sharing.html +465 -0
  128. package/dist/index.html +387 -0
  129. package/dist/llms.txt +18 -0
  130. package/dist/provenance.json +7 -0
  131. package/dist/schemas/index.html +11 -0
  132. package/dist/schemas/plugin-registry.schema.html +327 -0
  133. package/dist/schemas/plugin-schemas-notes.html +364 -0
  134. package/dist/schemas/plugin.schema.html +327 -0
  135. package/dist/schemas/plugins.schema.html +327 -0
  136. package/dist/schemas/v0/common.schema.html +386 -0
  137. package/dist/schemas/v0/index.html +11 -0
  138. package/dist/schemas/v0/plugin-registry.schema.html +547 -0
  139. package/dist/schemas/v0/plugin.schema.html +497 -0
  140. package/dist/schemas/v0/plugins.schema.html +406 -0
  141. package/dist/schemas/v0/site.schema.html +541 -0
  142. package/dist/schemas/v0/theme.schema.html +615 -0
  143. package/dist/schemas.html +351 -0
  144. package/dist/styles.css +1262 -0
  145. package/package.json +4 -2
  146. package/plugins-dist/callouts.css +32 -0
  147. package/plugins-dist/callouts.js +46 -0
  148. package/plugins-dist/slides-visuals.css +390 -0
  149. package/plugins-dist/slides-visuals.js +689 -0
  150. package/registry/plugins.yaml +35 -0
  151. package/schemas/README.md +10 -0
  152. package/schemas/plugin-registry.schema.json +5 -0
  153. package/schemas/plugin-schemas-notes.md +71 -0
  154. package/schemas/plugin.schema.json +5 -0
  155. package/schemas/plugins.schema.json +5 -0
  156. package/schemas/v0/common.schema.json +64 -0
  157. package/schemas/v0/plugin-registry.schema.json +225 -0
  158. package/schemas/v0/plugin.schema.json +175 -0
  159. package/schemas/v0/plugins.schema.json +84 -0
  160. package/schemas/v0/site.schema.json +56 -9
  161. package/schemas/v0/theme.schema.json +105 -22
  162. package/scripts/build.ts +158 -3
  163. package/scripts/bundle.ts +261 -95
  164. package/scripts/dev.ts +301 -11
  165. package/src/__tests__/build.test.ts +220 -1
  166. package/src/__tests__/bundle.test.ts +31 -0
  167. package/src/__tests__/cli.test.ts +14 -3
  168. package/src/__tests__/dev-plugin-errors.test.ts +20 -0
  169. package/src/__tests__/fixtures/fences/slides-visuals/invalid/bad-list-indent.md +5 -0
  170. package/src/__tests__/fixtures/fences/slides-visuals/invalid/blank-line.md +5 -0
  171. package/src/__tests__/fixtures/fences/slides-visuals/invalid/compare-object-items.md +9 -0
  172. package/src/__tests__/fixtures/fences/slides-visuals/invalid/flow-branching-no-source.md +5 -0
  173. package/src/__tests__/fixtures/fences/slides-visuals/invalid/flow-converging-no-target.md +6 -0
  174. package/src/__tests__/fixtures/fences/slides-visuals/invalid/indented-fence.md +4 -0
  175. package/src/__tests__/fixtures/fences/slides-visuals/invalid/staircase-empty-steps.md +3 -0
  176. package/src/__tests__/fixtures/fences/slides-visuals/invalid/stat-grid-missing-fields.md +5 -0
  177. package/src/__tests__/fixtures/fences/slides-visuals/invalid/timeline-horizontal-no-events.md +2 -0
  178. package/src/__tests__/fixtures/fences/slides-visuals/invalid/unknown-type.md +3 -0
  179. package/src/__tests__/fixtures/fences/slides-visuals/valid/compare.md +10 -0
  180. package/src/__tests__/fixtures/fences/slides-visuals/valid/comparison-table.md +14 -0
  181. package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-branching-no-split.md +7 -0
  182. package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-branching.md +8 -0
  183. package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-converging-no-merge.md +7 -0
  184. package/src/__tests__/fixtures/fences/slides-visuals/valid/flow-converging.md +8 -0
  185. package/src/__tests__/fixtures/fences/slides-visuals/valid/funnel.md +7 -0
  186. package/src/__tests__/fixtures/fences/slides-visuals/valid/kpi.md +5 -0
  187. package/src/__tests__/fixtures/fences/slides-visuals/valid/layer-cake.md +6 -0
  188. package/src/__tests__/fixtures/fences/slides-visuals/valid/pyramid.md +6 -0
  189. package/src/__tests__/fixtures/fences/slides-visuals/valid/quadrant-grid.md +8 -0
  190. package/src/__tests__/fixtures/fences/slides-visuals/valid/scorecard.md +13 -0
  191. package/src/__tests__/fixtures/fences/slides-visuals/valid/staircase-down.md +7 -0
  192. package/src/__tests__/fixtures/fences/slides-visuals/valid/staircase.md +8 -0
  193. package/src/__tests__/fixtures/fences/slides-visuals/valid/stat-grid.md +8 -0
  194. package/src/__tests__/fixtures/fences/slides-visuals/valid/timeline-horizontal.md +9 -0
  195. package/src/__tests__/fixtures/fences/slides-visuals/valid/timeline-vertical.md +10 -0
  196. package/src/__tests__/init.test.ts +35 -0
  197. package/src/__tests__/plugin-loader.test.ts +221 -0
  198. package/src/__tests__/shared.test.ts +451 -0
  199. package/src/__tests__/slides-visuals-fence-contract.test.ts +28 -0
  200. package/src/__tests__/slides-visuals-runtime-regressions.bun.test.ts +147 -0
  201. package/src/__tests__/styles.test.ts +35 -0
  202. package/src/cli.ts +9 -4
  203. package/src/plugin-loader.ts +245 -0
  204. package/src/shared.ts +650 -7
  205. package/src/site/styles.css +331 -0
  206. package/src/site/template.html +66 -5
  207. package/src/templates/deck.ts +186 -0
  208. package/src/templates/driver.ts +11 -1
  209. package/src/templates/minimal.ts +1 -0
@@ -0,0 +1,402 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>ADR-0005: Plugin Contract and Distribution Strategy - 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" class="active">ADR-0005-plugin-contract-and-distribution</a></li><li><a href="../../docs/decisions/DDR-0001-viewport-locked-layout.html">DDR-0001-viewport-locked-layout</a></li><li><a href="../../docs/decisions/DDR-0002-theme-system.html">DDR-0002-theme-system</a></li><li><a href="../../docs/decisions/DDR-0003-bounded-logo-slot.html">DDR-0003-bounded-logo-slot</a></li><li><a href="../../docs/decisions/DDR-0004-slides-rendering-model.html">DDR-0004-slides-rendering-model</a></li><li><a href="../../docs/decisions/DDR-0005-deterministic-layout-boundary.html">DDR-0005-deterministic-layout-boundary</a></li></ul></li><li><a href="../../schemas.html" class="nav-section">Schemas</a><ul><li><a href="../../schemas/plugin-registry.schema.html">plugin-registry.schema</a></li><li><a href="../../schemas/plugin-schemas-notes.html">plugin-schemas-notes</a></li><li><a href="../../schemas/plugin.schema.html">plugin.schema</a></li><li><a href="../../schemas/plugins.schema.html">plugins.schema</a></li><li><details><summary class="nav-group">v0</summary><ul><li><a href="../../schemas/v0/common.schema.html">common.schema</a></li><li><a href="../../schemas/v0/plugin-registry.schema.html">plugin-registry.schema</a></li><li><a href="../../schemas/v0/plugin.schema.html">plugin.schema</a></li><li><a href="../../schemas/v0/plugins.schema.html">plugins.schema</a></li><li><a href="../../schemas/v0/site.schema.html">site.schema</a></li><li><a href="../../schemas/v0/theme.schema.html">theme.schema</a></li></ul></details></li></ul></li></ul>
134
+ </div>
135
+ </nav>
136
+ <main class="content">
137
+ <article class="prose">
138
+ <nav class="breadcrumbs"><a href="../../docs/userguide/cli/build.html">Docs</a><span class="separator">›</span><a href="../../docs/decisions/ADR-0001-minimalist-site-code.html">Decisions</a><span class="separator">›</span><span>ADR-0005-plugin-contract-and-distribution</span></nav>
139
+
140
+ <h1 id="adr-0005-plugin-contract-and-distribution-strategy">ADR-0005: Plugin Contract and Distribution Strategy</h1>
141
+ <h2 id="status">Status</h2>
142
+ <p>Proposed</p>
143
+ <h2 id="context">Context</h2>
144
+ <p>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.</p>
145
+ <p>As of M1.1, basic slide <strong>shape primitives</strong> remain core CSS. Plugin scope starts at higher-level figures/widgets and engine integrations where deterministic core CSS stops.</p>
146
+ <p>Two operational choices must be explicit:</p>
147
+ <ol>
148
+ <li><strong>Contract stability</strong>: plugin authors and site operators need a clear, versioned interface that remains predictable.</li>
149
+ <li><strong>Repository strategy</strong>: plugins can live in the main repo or a separate repo; we need a pragmatic default and a low-risk migration path.</li>
150
+ </ol>
151
+ <h2 id="decision">Decision</h2>
152
+ <h3 id="1-treat-plugin-contract-as-versioned-api">1. Treat plugin contract as versioned API</h3>
153
+ <p>Kitfly will define a versioned plugin contract (<code>plugin.schema.json</code> + hook semantics) as a compatibility boundary.</p>
154
+ <p>Contract rules:</p>
155
+ <ul>
156
+ <li>Contract version is explicit (e.g. <code>contract: &quot;1&quot;</code>).</li>
157
+ <li>Breaking changes require a new major contract version.</li>
158
+ <li>Backward-compatible additions are allowed within a contract major version.</li>
159
+ <li>Deprecations must include migration guidance before removal.</li>
160
+ </ul>
161
+ <h3 id="2-start-plugins-in-repo-for-v020">2. Start plugins in-repo for v0.2.0</h3>
162
+ <p>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.</p>
163
+ <p>Why now:</p>
164
+ <ul>
165
+ <li>Faster iteration while contract and hooks are stabilizing.</li>
166
+ <li>Lower coordination overhead across core + plugin changes.</li>
167
+ <li>Simpler QA and dogfooding in a single branch/CI surface.</li>
168
+ </ul>
169
+ <h3 id="3-keep-extraction-path-explicit">3. Keep extraction path explicit</h3>
170
+ <p>In-repo is not permanent by requirement. Plugin layout, manifest format, and loader/registry interfaces must remain portable so plugins can move to <code>kitfly-plugins</code> later with minimal disruption.</p>
171
+ <p>Extraction trigger signals:</p>
172
+ <ul>
173
+ <li>plugin maintenance cadence diverges from core,</li>
174
+ <li>external contribution volume rises,</li>
175
+ <li>plugin release/security pipeline becomes materially heavier.</li>
176
+ </ul>
177
+ <h3 id="4-security-and-policy-baseline">4. Security and policy baseline</h3>
178
+ <p>Distribution policy applies regardless of repo location:</p>
179
+ <ul>
180
+ <li>version pinning required,</li>
181
+ <li>checksum verification required,</li>
182
+ <li>SRI required for CDN assets,</li>
183
+ <li>untrusted third-party plugins denied by default unless explicit opt-in.</li>
184
+ </ul>
185
+ <h2 id="consequences">Consequences</h2>
186
+ <h3 id="positive">Positive</h3>
187
+ <ul>
188
+ <li>Contract clarity reduces integration breakage and support ambiguity.</li>
189
+ <li>In-repo startup reduces delivery friction for v0.2.0.</li>
190
+ <li>Future repo split remains available without contract rewrite.</li>
191
+ </ul>
192
+ <h3 id="negative">Negative</h3>
193
+ <ul>
194
+ <li>Core repo grows in scope and review surface in the short term.</li>
195
+ <li>Requires discipline to prevent plugin internals from leaking into core assumptions.</li>
196
+ </ul>
197
+ <h3 id="neutral">Neutral</h3>
198
+ <ul>
199
+ <li>Repo location is an implementation detail; contract/API stability is the true long-term commitment.</li>
200
+ </ul>
201
+ <h2 id="compatibility-policy-initial">Compatibility Policy (Initial)</h2>
202
+ <ul>
203
+ <li>Contract v1 supported throughout v0.2.x.</li>
204
+ <li>If contract v2 is introduced, v1 support remains for at least one minor release.</li>
205
+ <li>Compatibility matrix (kitfly version ↔ contract version) must be documented in plugin docs.</li>
206
+ </ul>
207
+ <h2 id="alternatives-considered">Alternatives Considered</h2>
208
+ <h3 id="separate-plugin-repo-immediately">Separate plugin repo immediately</h3>
209
+ <p>Pros: cleaner ownership and release boundaries from day one.
210
+ Cons: slower early iteration and more cross-repo coordination while contracts are still fluid.</p>
211
+ <p>Decision: defer split until signals justify it.</p>
212
+ <h3 id="no-formal-contract-versioning">No formal contract versioning</h3>
213
+ <p>Rejected: too much ambiguity and high breakage risk once plugins exist in the wild.</p>
214
+ <h2 id="references">References</h2>
215
+ <ul>
216
+ <li><a href="DDR-0005-deterministic-layout-boundary.md">DDR-0005: Deterministic Layout Boundary</a></li>
217
+ <li><a href="../../content/reference/design-catalog.md">Design Catalog: Shapes and Figures</a></li>
218
+ <li><a href="ADR-0001-minimalist-site-code.md">ADR-0001: Minimalist Site Code</a></li>
219
+ </ul>
220
+
221
+ </article>
222
+ <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="#1-treat-plugin-contract-as-versioned-api">1. Treat plugin contract as versioned API</a></li><li class="toc-h3"><a href="#2-start-plugins-in-repo-for-v020">2. Start plugins in-repo for v0.2.0</a></li><li class="toc-h3"><a href="#3-keep-extraction-path-explicit">3. Keep extraction path explicit</a></li><li class="toc-h3"><a href="#4-security-and-policy-baseline">4. Security and policy baseline</a></li><li><a href="#consequences">Consequences</a></li><li class="toc-h3"><a href="#positive">Positive</a></li><li class="toc-h3"><a href="#negative">Negative</a></li><li class="toc-h3"><a href="#neutral">Neutral</a></li><li><a href="#compatibility-policy-initial">Compatibility Policy (Initial)</a></li><li><a href="#alternatives-considered">Alternatives Considered</a></li><li class="toc-h3"><a href="#separate-plugin-repo-immediately">Separate plugin repo immediately</a></li><li class="toc-h3"><a href="#no-formal-contract-versioning">No formal contract versioning</a></li><li><a href="#references">References</a></li></ul></aside>
223
+ </main>
224
+ </div>
225
+
226
+ <footer class="site-footer">
227
+ <div class="footer-content">
228
+ <div class="footer-left">
229
+ <span class="footer-version">v0.2.1</span>
230
+ <span class="footer-separator">·</span>
231
+ <span class="footer-commit" title="Commit: 30dfc01">Published 2026-02-15</span>
232
+ </div>
233
+ <div class="footer-center">
234
+ <span class="footer-copyright"><a href="https://3leaps.net" class="footer-link">© 2026 3 Leaps, LLC</a></span>
235
+ <span class="footer-separator">·</span><a href="/" class="footer-link">Kitfly</a>
236
+ </div>
237
+ <div class="footer-right">
238
+ <a href="https://kitfly.dev" class="footer-link">Built with Kitfly</a>
239
+ </div>
240
+ </div>
241
+ </footer>
242
+ <!-- Syntax highlighting - Prism.js -->
243
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-core.min.js"></script>
244
+ <script src="https://cdn.jsdelivr.net/npm/prismjs@1/plugins/autoloader/prism-autoloader.min.js"></script>
245
+ <!-- Mermaid diagram support -->
246
+ <script type="module">
247
+ import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
248
+
249
+ function getMermaidTheme() {
250
+ const theme = document.documentElement.getAttribute('data-theme');
251
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
252
+ const isDark = theme === 'dark' || (!theme && prefersDark);
253
+ return isDark ? 'dark' : 'neutral';
254
+ }
255
+
256
+ mermaid.initialize({
257
+ startOnLoad: true,
258
+ theme: getMermaidTheme()
259
+ });
260
+
261
+ // Re-render mermaid diagrams when theme changes
262
+ window.reinitMermaid = async function() {
263
+ mermaid.initialize({ startOnLoad: false, theme: getMermaidTheme() });
264
+ const diagrams = document.querySelectorAll('.mermaid');
265
+ for (const el of diagrams) {
266
+ const code = el.getAttribute('data-mermaid-source');
267
+ if (code) {
268
+ el.innerHTML = code;
269
+ el.removeAttribute('data-processed');
270
+ }
271
+ }
272
+ await mermaid.run({ nodes: diagrams });
273
+ };
274
+ </script>
275
+
276
+ <script>
277
+ function toggleTheme() {
278
+ const html = document.documentElement;
279
+ const current = html.getAttribute('data-theme');
280
+ const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
281
+
282
+ let next;
283
+ if (current === 'dark') {
284
+ next = 'light';
285
+ } else if (current === 'light') {
286
+ next = 'dark';
287
+ } else {
288
+ // No explicit theme set, toggle from system preference
289
+ next = prefersDark ? 'light' : 'dark';
290
+ }
291
+
292
+ html.setAttribute('data-theme', next);
293
+ localStorage.setItem('theme', next);
294
+
295
+ // Switch Prism theme
296
+ const prismLight = document.getElementById('prism-light');
297
+ const prismDark = document.getElementById('prism-dark');
298
+ if (next === 'dark') {
299
+ prismLight?.setAttribute('disabled', '');
300
+ prismDark?.removeAttribute('disabled');
301
+ } else {
302
+ prismLight?.removeAttribute('disabled');
303
+ prismDark?.setAttribute('disabled', '');
304
+ }
305
+
306
+ // Re-render mermaid diagrams with new theme
307
+ if (window.reinitMermaid) {
308
+ window.reinitMermaid();
309
+ }
310
+ }
311
+
312
+ // Slides mode hash routing
313
+ (function initSlidesMode() {
314
+ const shell = document.querySelector('.slides-shell');
315
+ if (!shell) return;
316
+
317
+ const slides = Array.from(document.querySelectorAll('.slide'));
318
+ if (!slides.length) return;
319
+
320
+ const prevBtn = document.querySelector('.slide-prev');
321
+ const nextBtn = document.querySelector('.slide-next');
322
+ const counter = document.querySelector('.slide-counter');
323
+ const progressBar = document.querySelector('.slide-progress-bar');
324
+ const navLinks = Array.from(document.querySelectorAll('.sidebar-nav a[href^="#slide-"]'));
325
+ let current = 0;
326
+
327
+ function setActive(n) {
328
+ current = Math.max(0, Math.min(n, slides.length - 1));
329
+ slides.forEach((slide, idx) => slide.classList.toggle('active', idx === current));
330
+ navLinks.forEach((link) => {
331
+ const active = link.getAttribute('href') === '#' + slides[current].id;
332
+ link.classList.toggle('active', active);
333
+ });
334
+ if (counter) counter.textContent = (current + 1) + ' / ' + slides.length;
335
+ if (progressBar) progressBar.style.width = (((current + 1) / slides.length) * 100) + '%';
336
+ if (prevBtn) prevBtn.disabled = current === 0;
337
+ if (nextBtn) nextBtn.disabled = current === slides.length - 1;
338
+ history.replaceState(null, '', '#' + slides[current].id);
339
+ }
340
+
341
+ function setFromHash() {
342
+ const hash = window.location.hash || '';
343
+ const idx = slides.findIndex((s) => '#' + s.id === hash);
344
+ if (idx >= 0) setActive(idx);
345
+ else setActive(0);
346
+ }
347
+
348
+ prevBtn?.addEventListener('click', () => setActive(current - 1));
349
+ nextBtn?.addEventListener('click', () => setActive(current + 1));
350
+
351
+ document.addEventListener('keydown', (e) => {
352
+ if (e.key === 'ArrowRight' || e.key === ' ') {
353
+ e.preventDefault();
354
+ setActive(current + 1);
355
+ } else if (e.key === 'ArrowLeft') {
356
+ e.preventDefault();
357
+ setActive(current - 1);
358
+ } else if (e.key === 'Home') {
359
+ e.preventDefault();
360
+ setActive(0);
361
+ } else if (e.key === 'End') {
362
+ e.preventDefault();
363
+ setActive(slides.length - 1);
364
+ }
365
+ });
366
+
367
+ window.addEventListener('hashchange', setFromHash);
368
+ setFromHash();
369
+ })();
370
+
371
+ // Copy code button
372
+ document.querySelectorAll('.prose pre code').forEach(block => {
373
+ const button = document.createElement('button');
374
+ button.className = 'copy-button';
375
+ button.textContent = 'Copy';
376
+ button.onclick = async () => {
377
+ await navigator.clipboard.writeText(block.textContent);
378
+ button.textContent = 'Copied!';
379
+ setTimeout(() => button.textContent = 'Copy', 2000);
380
+ };
381
+ block.parentElement.appendChild(button);
382
+ });
383
+
384
+ // Mobile nav toggle
385
+ function toggleNav() {
386
+ document.querySelector('.sidebar').classList.toggle('open');
387
+ }
388
+
389
+ // Close nav when clicking outside on mobile
390
+ document.addEventListener('click', (e) => {
391
+ const sidebar = document.querySelector('.sidebar');
392
+ const toggle = document.querySelector('.nav-toggle');
393
+ if (sidebar.classList.contains('open') &&
394
+ !sidebar.contains(e.target) &&
395
+ !toggle.contains(e.target)) {
396
+ sidebar.classList.remove('open');
397
+ }
398
+ });
399
+ </script>
400
+
401
+ </body>
402
+ </html>