decantr 0.9.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/AGENTS.md +868 -0
- package/CHANGELOG.md +255 -0
- package/CLAUDE.md +178 -0
- package/LICENSE +21 -0
- package/README.md +229 -0
- package/cli/art.js +127 -0
- package/cli/commands/a11y.js +61 -0
- package/cli/commands/audit.js +225 -0
- package/cli/commands/build.js +38 -0
- package/cli/commands/dev.js +18 -0
- package/cli/commands/doctor.js +197 -0
- package/cli/commands/figma-sync.js +48 -0
- package/cli/commands/figma-tokens.js +55 -0
- package/cli/commands/generate.js +26 -0
- package/cli/commands/init.js +116 -0
- package/cli/commands/lint.js +209 -0
- package/cli/commands/mcp.js +530 -0
- package/cli/commands/migrate.js +175 -0
- package/cli/commands/test.js +38 -0
- package/cli/commands/validate.js +354 -0
- package/cli/index.js +113 -0
- package/package.json +95 -0
- package/reference/atoms.md +517 -0
- package/reference/behaviors.md +384 -0
- package/reference/build-tooling.md +275 -0
- package/reference/color-guidelines.md +965 -0
- package/reference/component-lifecycle.md +137 -0
- package/reference/compound-spacing.md +95 -0
- package/reference/decantation-process.md +499 -0
- package/reference/dev-server-routes.md +93 -0
- package/reference/form-system.md +253 -0
- package/reference/i18n.md +336 -0
- package/reference/icons.md +576 -0
- package/reference/llm-primer.md +953 -0
- package/reference/plugins.md +252 -0
- package/reference/registry-consumption.md +76 -0
- package/reference/router.md +217 -0
- package/reference/shells.md +116 -0
- package/reference/spatial-guidelines.md +541 -0
- package/reference/ssr.md +234 -0
- package/reference/state-data.md +215 -0
- package/reference/state-patterns.md +166 -0
- package/reference/state.md +194 -0
- package/reference/style-system.md +110 -0
- package/reference/tokens.md +460 -0
- package/src/app.js +19 -0
- package/src/chart/_animate.js +266 -0
- package/src/chart/_base.js +109 -0
- package/src/chart/_data.js +209 -0
- package/src/chart/_format.js +106 -0
- package/src/chart/_interact.js +364 -0
- package/src/chart/_palette.js +105 -0
- package/src/chart/_renderer.js +52 -0
- package/src/chart/_scene.js +262 -0
- package/src/chart/_shared.js +371 -0
- package/src/chart/index.js +637 -0
- package/src/chart/layouts/_layout-base.js +328 -0
- package/src/chart/layouts/cartesian.js +148 -0
- package/src/chart/layouts/hierarchy.js +562 -0
- package/src/chart/layouts/polar.js +101 -0
- package/src/chart/renderers/canvas.js +179 -0
- package/src/chart/renderers/svg.js +256 -0
- package/src/chart/renderers/webgpu.js +715 -0
- package/src/chart/types/_type-base.js +26 -0
- package/src/chart/types/area.js +134 -0
- package/src/chart/types/bar.js +173 -0
- package/src/chart/types/box-plot.js +125 -0
- package/src/chart/types/bubble.js +63 -0
- package/src/chart/types/candlestick.js +115 -0
- package/src/chart/types/chord.js +85 -0
- package/src/chart/types/combination.js +108 -0
- package/src/chart/types/funnel.js +68 -0
- package/src/chart/types/gauge.js +163 -0
- package/src/chart/types/heatmap.js +98 -0
- package/src/chart/types/histogram.js +71 -0
- package/src/chart/types/line.js +111 -0
- package/src/chart/types/org-chart.js +93 -0
- package/src/chart/types/pie.js +81 -0
- package/src/chart/types/radar.js +96 -0
- package/src/chart/types/radial.js +68 -0
- package/src/chart/types/range-area.js +55 -0
- package/src/chart/types/range-bar.js +61 -0
- package/src/chart/types/sankey.js +73 -0
- package/src/chart/types/scatter.js +66 -0
- package/src/chart/types/sparkline.js +81 -0
- package/src/chart/types/sunburst.js +69 -0
- package/src/chart/types/swimlane.js +88 -0
- package/src/chart/types/treemap.js +62 -0
- package/src/chart/types/waterfall.js +100 -0
- package/src/components/_base.js +1658 -0
- package/src/components/_behaviors.js +1140 -0
- package/src/components/_primitives.js +534 -0
- package/src/components/_qr-encoder.js +539 -0
- package/src/components/accordion.js +207 -0
- package/src/components/affix.js +62 -0
- package/src/components/alert-dialog.js +75 -0
- package/src/components/alert.js +47 -0
- package/src/components/aspect-ratio.js +24 -0
- package/src/components/avatar-group.js +55 -0
- package/src/components/avatar.js +38 -0
- package/src/components/back-top.js +75 -0
- package/src/components/badge.js +74 -0
- package/src/components/banner.js +68 -0
- package/src/components/breadcrumb.js +162 -0
- package/src/components/button.js +115 -0
- package/src/components/calendar.js +131 -0
- package/src/components/card.js +192 -0
- package/src/components/carousel.js +98 -0
- package/src/components/cascader.js +261 -0
- package/src/components/checkbox.js +80 -0
- package/src/components/chip.js +81 -0
- package/src/components/code-block.js +82 -0
- package/src/components/collapsible.js +50 -0
- package/src/components/color-palette.js +438 -0
- package/src/components/color-picker.js +314 -0
- package/src/components/combobox.js +181 -0
- package/src/components/command.js +174 -0
- package/src/components/comment.js +206 -0
- package/src/components/context-menu.js +76 -0
- package/src/components/data-table.js +724 -0
- package/src/components/date-picker.js +217 -0
- package/src/components/date-range-picker.js +244 -0
- package/src/components/datetime-picker.js +271 -0
- package/src/components/descriptions.js +68 -0
- package/src/components/drawer.js +179 -0
- package/src/components/dropdown.js +88 -0
- package/src/components/empty.js +41 -0
- package/src/components/float-button.js +90 -0
- package/src/components/form.js +106 -0
- package/src/components/hover-card.js +49 -0
- package/src/components/icon.js +87 -0
- package/src/components/image.js +97 -0
- package/src/components/index.js +117 -0
- package/src/components/input-group.js +75 -0
- package/src/components/input-number.js +155 -0
- package/src/components/input-otp.js +178 -0
- package/src/components/input.js +91 -0
- package/src/components/kbd.js +36 -0
- package/src/components/label.js +25 -0
- package/src/components/list.js +118 -0
- package/src/components/masked-input.js +236 -0
- package/src/components/mentions.js +165 -0
- package/src/components/menu.js +259 -0
- package/src/components/message.js +80 -0
- package/src/components/modal.js +147 -0
- package/src/components/navigation-menu.js +166 -0
- package/src/components/notification.js +84 -0
- package/src/components/pagination.js +104 -0
- package/src/components/placeholder.js +132 -0
- package/src/components/popconfirm.js +70 -0
- package/src/components/popover.js +58 -0
- package/src/components/progress.js +61 -0
- package/src/components/qrcode.js +251 -0
- package/src/components/radiogroup.js +120 -0
- package/src/components/range-slider.js +176 -0
- package/src/components/rate.js +186 -0
- package/src/components/resizable.js +83 -0
- package/src/components/result.js +57 -0
- package/src/components/scroll-area.js +43 -0
- package/src/components/segmented.js +97 -0
- package/src/components/select.js +165 -0
- package/src/components/separator.js +31 -0
- package/src/components/shell.js +407 -0
- package/src/components/skeleton.js +39 -0
- package/src/components/slider.js +141 -0
- package/src/components/sortable-list.js +176 -0
- package/src/components/space.js +42 -0
- package/src/components/spinner.js +112 -0
- package/src/components/splitter.js +147 -0
- package/src/components/statistic.js +136 -0
- package/src/components/steps.js +99 -0
- package/src/components/switch.js +95 -0
- package/src/components/table.js +44 -0
- package/src/components/tabs.js +216 -0
- package/src/components/tag.js +115 -0
- package/src/components/textarea.js +82 -0
- package/src/components/time-picker.js +153 -0
- package/src/components/time-range-picker.js +170 -0
- package/src/components/timeline.js +226 -0
- package/src/components/toast.js +71 -0
- package/src/components/toggle.js +213 -0
- package/src/components/tooltip.js +57 -0
- package/src/components/tour.js +159 -0
- package/src/components/transfer.js +163 -0
- package/src/components/tree-select.js +274 -0
- package/src/components/tree.js +141 -0
- package/src/components/typography.js +136 -0
- package/src/components/upload.js +118 -0
- package/src/components/visually-hidden.js +20 -0
- package/src/components/watermark.js +124 -0
- package/src/core/index.js +539 -0
- package/src/core/lifecycle.js +69 -0
- package/src/css/atoms.js +651 -0
- package/src/css/components.js +940 -0
- package/src/css/derive.js +1296 -0
- package/src/css/index.js +265 -0
- package/src/css/runtime.js +268 -0
- package/src/css/styles/addons/bioluminescent.js +93 -0
- package/src/css/styles/addons/clay.js +70 -0
- package/src/css/styles/addons/clean.js +57 -0
- package/src/css/styles/addons/command-center.js +143 -0
- package/src/css/styles/addons/dopamine.js +83 -0
- package/src/css/styles/addons/editorial.js +80 -0
- package/src/css/styles/addons/glassmorphism.js +99 -0
- package/src/css/styles/addons/liquid-glass.js +105 -0
- package/src/css/styles/addons/prismatic.js +100 -0
- package/src/css/styles/addons/retro.js +63 -0
- package/src/css/styles/auradecantism.js +96 -0
- package/src/css/theme-registry.js +444 -0
- package/src/data/entity.js +281 -0
- package/src/data/index.js +13 -0
- package/src/data/persist.js +225 -0
- package/src/data/query.js +839 -0
- package/src/data/realtime.js +299 -0
- package/src/data/url.js +177 -0
- package/src/data/worker.js +134 -0
- package/src/explorer/archetypes.js +243 -0
- package/src/explorer/atoms.js +228 -0
- package/src/explorer/charts.js +497 -0
- package/src/explorer/components.js +129 -0
- package/src/explorer/foundations.js +949 -0
- package/src/explorer/icons.js +178 -0
- package/src/explorer/patterns.js +247 -0
- package/src/explorer/recipes.js +194 -0
- package/src/explorer/shared/pattern-examples.js +1337 -0
- package/src/explorer/shared/showcase-renderer.js +958 -0
- package/src/explorer/shared/spec-table.js +41 -0
- package/src/explorer/shared/usage-links.js +87 -0
- package/src/explorer/shell-config.js +10 -0
- package/src/explorer/shells.js +551 -0
- package/src/explorer/styles.js +161 -0
- package/src/explorer/tokens.js +262 -0
- package/src/explorer/tools.js +525 -0
- package/src/form/index.js +804 -0
- package/src/i18n/index.js +251 -0
- package/src/icons/essential.js +479 -0
- package/src/icons/index.js +53 -0
- package/src/plugins/index.js +282 -0
- package/src/registry/archetypes/content-site.json +71 -0
- package/src/registry/archetypes/docs-explorer.json +23 -0
- package/src/registry/archetypes/ecommerce.json +104 -0
- package/src/registry/archetypes/financial-dashboard.json +77 -0
- package/src/registry/archetypes/index.json +41 -0
- package/src/registry/archetypes/portfolio.json +82 -0
- package/src/registry/archetypes/recipe-community.json +159 -0
- package/src/registry/archetypes/saas-dashboard.json +86 -0
- package/src/registry/architect/cross-cutting.json +45 -0
- package/src/registry/architect/domains/ecommerce.json +294 -0
- package/src/registry/architect/domains/financial-services.json +302 -0
- package/src/registry/architect/index.json +26 -0
- package/src/registry/architect/traits.json +379 -0
- package/src/registry/atoms.json +16 -0
- package/src/registry/chart-showcase.json +160 -0
- package/src/registry/chart.json +136 -0
- package/src/registry/components.json +8616 -0
- package/src/registry/core.json +216 -0
- package/src/registry/css.json +319 -0
- package/src/registry/data.json +135 -0
- package/src/registry/foundations.json +11 -0
- package/src/registry/icons.json +463 -0
- package/src/registry/index.json +101 -0
- package/src/registry/patterns/activity-feed.json +37 -0
- package/src/registry/patterns/article-content.json +27 -0
- package/src/registry/patterns/auth-form.json +37 -0
- package/src/registry/patterns/author-card.json +20 -0
- package/src/registry/patterns/card-grid.json +127 -0
- package/src/registry/patterns/category-nav.json +26 -0
- package/src/registry/patterns/chart-grid.json +36 -0
- package/src/registry/patterns/chat-interface.json +37 -0
- package/src/registry/patterns/checklist-card.json +55 -0
- package/src/registry/patterns/comparison-panel.json +27 -0
- package/src/registry/patterns/component-showcase.json +24 -0
- package/src/registry/patterns/contact-form.json +31 -0
- package/src/registry/patterns/cta-section.json +20 -0
- package/src/registry/patterns/data-table.json +37 -0
- package/src/registry/patterns/detail-header.json +83 -0
- package/src/registry/patterns/detail-panel.json +27 -0
- package/src/registry/patterns/explorer-shell.json +22 -0
- package/src/registry/patterns/filter-bar.json +33 -0
- package/src/registry/patterns/filter-sidebar.json +27 -0
- package/src/registry/patterns/form-sections.json +110 -0
- package/src/registry/patterns/goal-tracker.json +27 -0
- package/src/registry/patterns/hero.json +107 -0
- package/src/registry/patterns/index.json +47 -0
- package/src/registry/patterns/kpi-grid.json +36 -0
- package/src/registry/patterns/media-gallery.json +20 -0
- package/src/registry/patterns/order-history.json +20 -0
- package/src/registry/patterns/pagination.json +19 -0
- package/src/registry/patterns/photo-to-recipe.json +36 -0
- package/src/registry/patterns/pipeline-tracker.json +28 -0
- package/src/registry/patterns/post-list.json +27 -0
- package/src/registry/patterns/pricing-table.json +32 -0
- package/src/registry/patterns/scorecard.json +28 -0
- package/src/registry/patterns/search-bar.json +20 -0
- package/src/registry/patterns/specimen-grid.json +19 -0
- package/src/registry/patterns/stat-card.json +55 -0
- package/src/registry/patterns/stats-bar.json +55 -0
- package/src/registry/patterns/steps-card.json +55 -0
- package/src/registry/patterns/table-of-contents.json +19 -0
- package/src/registry/patterns/testimonials.json +21 -0
- package/src/registry/patterns/timeline.json +27 -0
- package/src/registry/patterns/token-inspector.json +21 -0
- package/src/registry/patterns/wizard.json +27 -0
- package/src/registry/recipe-auradecantism.json +69 -0
- package/src/registry/recipe-clean.json +65 -0
- package/src/registry/recipe-command-center.json +78 -0
- package/src/registry/router.json +73 -0
- package/src/registry/schema/README.md +197 -0
- package/src/registry/skeletons.json +259 -0
- package/src/registry/state.json +137 -0
- package/src/registry/tokens.json +40 -0
- package/src/router/hash.js +17 -0
- package/src/router/history.js +18 -0
- package/src/router/index.js +598 -0
- package/src/ssr/index.js +922 -0
- package/src/state/arrays.js +181 -0
- package/src/state/devtools.js +647 -0
- package/src/state/index.js +498 -0
- package/src/state/middleware.js +288 -0
- package/src/state/scheduler.js +206 -0
- package/src/state/store.js +300 -0
- package/src/tags/index.js +19 -0
- package/src/tannins/auth.js +396 -0
- package/src/test/dom.js +352 -0
- package/src/test/index.js +62 -0
- package/src/test/state.js +306 -0
- package/tools/a11y-audit.js +487 -0
- package/tools/analyzer.js +315 -0
- package/tools/audit.js +706 -0
- package/tools/builder.js +1422 -0
- package/tools/css-extract.js +188 -0
- package/tools/dev-server.js +316 -0
- package/tools/dts-gen.js +1260 -0
- package/tools/figma-components.js +329 -0
- package/tools/figma-patterns.js +516 -0
- package/tools/figma-plugin/code.js +453 -0
- package/tools/figma-plugin/manifest.json +14 -0
- package/tools/figma-plugin/ui.html +268 -0
- package/tools/figma-render.js +293 -0
- package/tools/figma-tokens.js +712 -0
- package/tools/figma-upload.js +318 -0
- package/tools/generate.js +738 -0
- package/tools/icons.js +133 -0
- package/tools/init-templates.js +265 -0
- package/tools/install-hooks.sh +5 -0
- package/tools/migrations/0.5.0.js +53 -0
- package/tools/migrations/0.6.0.js +95 -0
- package/tools/minify.js +170 -0
- package/tools/pre-commit +4 -0
- package/tools/registry.js +662 -0
- package/tools/reset-playground.js +61 -0
- package/tools/starter-templates/content-site/app.js +49 -0
- package/tools/starter-templates/content-site/essence.js +19 -0
- package/tools/starter-templates/content-site/pages.js +31 -0
- package/tools/starter-templates/ecommerce/app.js +50 -0
- package/tools/starter-templates/ecommerce/essence.js +19 -0
- package/tools/starter-templates/ecommerce/pages.js +31 -0
- package/tools/starter-templates/landing-page/app.js +38 -0
- package/tools/starter-templates/landing-page/essence.js +18 -0
- package/tools/starter-templates/landing-page/pages.js +21 -0
- package/tools/starter-templates/portfolio/app.js +45 -0
- package/tools/starter-templates/portfolio/essence.js +19 -0
- package/tools/starter-templates/portfolio/pages.js +33 -0
- package/tools/starter-templates/saas-dashboard/app.js +70 -0
- package/tools/starter-templates/saas-dashboard/essence.js +19 -0
- package/tools/starter-templates/saas-dashboard/pages.js +31 -0
- package/tools/verify-pack.js +203 -0
- package/types/chart.d.ts +77 -0
- package/types/components.d.ts +587 -0
- package/types/core.d.ts +89 -0
- package/types/css.d.ts +149 -0
- package/types/data.d.ts +238 -0
- package/types/form.d.ts +164 -0
- package/types/i18n.d.ts +51 -0
- package/types/icons.d.ts +27 -0
- package/types/index.d.ts +13 -0
- package/types/router.d.ts +116 -0
- package/types/ssr.d.ts +102 -0
- package/types/state.d.ts +83 -0
- package/types/tags.d.ts +62 -0
- package/types/tannins.d.ts +63 -0
- package/types/test.d.ts +48 -0
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
# The Decantation Process
|
|
2
|
+
|
|
3
|
+
The intelligence layer between user intent and generated code. A formalized methodology that decomposes raw UI requirements into structured, drift-free specifications.
|
|
4
|
+
|
|
5
|
+
## The Six Stages
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
POUR → SETTLE → CLARIFY → DECANT → SERVE → AGE
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### POUR (Intent Capture)
|
|
12
|
+
User expresses what they want in natural language. No forms, no wizards.
|
|
13
|
+
|
|
14
|
+
### SETTLE (Intent Decomposition)
|
|
15
|
+
The LLM decomposes intent into five named layers:
|
|
16
|
+
|
|
17
|
+
| Layer | Resolves | Registry Source |
|
|
18
|
+
|-------|----------|-----------------|
|
|
19
|
+
| **Terroir** | Domain archetype | `src/registry/archetypes/` |
|
|
20
|
+
| **Vintage** | Style + mode + recipe | `src/css/styles/` + `src/registry/recipe-*.json` |
|
|
21
|
+
| **Character** | Brand personality traits | User-defined (e.g. "tactical", "minimal") |
|
|
22
|
+
| **Structure** | Page/view map | Archetype `pages` + user customization |
|
|
23
|
+
| **Tannins** | Functional systems | Archetype `tannins` + user requirements |
|
|
24
|
+
|
|
25
|
+
### CLARIFY (Essence Crystallization)
|
|
26
|
+
The LLM writes `decantr.essence.json` — the project's persistent DNA. User confirms. From this point, every decision references the Essence.
|
|
27
|
+
|
|
28
|
+
### Pattern Design Review Gate
|
|
29
|
+
|
|
30
|
+
**Mandatory checkpoint between CLARIFY and DECANT.** Before resolving any Blend specs, review every pattern referenced in the Essence's `blend` arrays against this checklist:
|
|
31
|
+
|
|
32
|
+
1. **Can this be a preset on an existing pattern?** Check the pattern registry (`src/registry/patterns/`) for structurally similar patterns that already support presets. If the desired variation differs only in content slots, label placement, or density — add a preset instead of a new pattern file.
|
|
33
|
+
2. **Does a structurally similar pattern already exist?** If two patterns share the same grid layout, component set, and slot structure but differ in domain-specific naming, merge the new one as a preset on the existing pattern. Example: `recipe-stats-bar` and `product-stats-bar` are the same structure — one pattern with domain presets.
|
|
34
|
+
3. **Is the new pattern reusable across 2+ domains?** A pattern must be justified by cross-domain utility. If a pattern is only useful within a single archetype, it should be a preset on a more general pattern. Exception: if the archetype is new and the pattern is fundamental to its identity.
|
|
35
|
+
4. **Does the domain-specific name justify a standalone file?** Only create a new pattern file when the structure (grid layout, component composition, slot arrangement) is fundamentally different from all existing patterns. A different name alone does not justify a new file.
|
|
36
|
+
|
|
37
|
+
**If any check fails**, refactor the blend to reference an existing pattern with a preset:
|
|
38
|
+
```json
|
|
39
|
+
{ "pattern": "stats-bar", "preset": "recipe", "as": "recipe-stats-bar" }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Proceeding to DECANT without completing this review is a Cork violation.**
|
|
43
|
+
|
|
44
|
+
### DECANT (Spec Resolution)
|
|
45
|
+
Each Structure page resolves to a **Blend** — a row-based layout tree that specifies spatial arrangement of patterns. The archetype provides `default_blend` per page; the LLM copies it into the Essence's `blend` and customizes.
|
|
46
|
+
|
|
47
|
+
### SERVE (Code Generation)
|
|
48
|
+
Code generated from resolved Blend specs. The LLM reads each page's `blend` array and applies the SERVE algorithm (see Blend Spec below). No spatial improvisation — row order, column splits, and responsive breakpoints are all pre-specified.
|
|
49
|
+
|
|
50
|
+
### AGE (Session Fortification)
|
|
51
|
+
On every subsequent prompt, the LLM reads the Essence first. New pages inherit the Vintage. Drift is detected and flagged.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Vocabulary
|
|
56
|
+
|
|
57
|
+
### Project Identity
|
|
58
|
+
|
|
59
|
+
| Term | Definition |
|
|
60
|
+
|------|-----------|
|
|
61
|
+
| **Terroir** | Domain archetype. What kind of product this is. |
|
|
62
|
+
| **Vintage** | Visual identity — style + mode + recipe + shape. |
|
|
63
|
+
| **Character** | Brand personality as trait words. Guides density, tone, animation. |
|
|
64
|
+
| **Essence** | The persistent project DNA file (`decantr.essence.json`). |
|
|
65
|
+
|
|
66
|
+
### Architecture
|
|
67
|
+
|
|
68
|
+
| Term | Definition |
|
|
69
|
+
|------|-----------|
|
|
70
|
+
| **Vessel** | App container type + routing strategy (SPA/MPA, hash/history). |
|
|
71
|
+
| **Structure** | Page/view map — all screens in the app. |
|
|
72
|
+
| **Skeleton** | Layout type per page (sidebar-main, top-nav-main, full-bleed, centered). |
|
|
73
|
+
|
|
74
|
+
### Composition
|
|
75
|
+
|
|
76
|
+
| Term | Definition |
|
|
77
|
+
|------|-----------|
|
|
78
|
+
| **Blend** | Per-page spatial arrangement — a row-based layout tree specifying pattern order, column splits, and responsive breakpoints. |
|
|
79
|
+
| **Recipe** | Visual language composition rules — how standard components are wrapped/decorated differently. |
|
|
80
|
+
| **Plumbing** | State signals, stores, and data flows for the page. |
|
|
81
|
+
| **Pattern** | Reusable UI building block (kpi-grid, data-table, wizard, etc.) referenced by archetypes. |
|
|
82
|
+
|
|
83
|
+
### Visual Surface
|
|
84
|
+
|
|
85
|
+
| Term | Definition |
|
|
86
|
+
|------|-----------|
|
|
87
|
+
| **Bouquet** | Colors — palette tokens from `derive()` using OKLCH color math. Character traits map to palette personality (minimal->low chroma, bold->high chroma, professional->cool blue, technical->monochrome). See `reference/color-guidelines.md` §13. |
|
|
88
|
+
| **Body** | Typography — font, weight, spacing from style definition. |
|
|
89
|
+
| **Finish** | Motion + interaction — durations, easing from personality traits. |
|
|
90
|
+
| **Clarity** | White space — density, compound spacing from density trait. The Clarity layer is fully specified in `reference/spatial-guidelines.md` §17 Clarity Profile. |
|
|
91
|
+
|
|
92
|
+
### Drift Prevention
|
|
93
|
+
|
|
94
|
+
| Term | Definition |
|
|
95
|
+
|------|-----------|
|
|
96
|
+
| **Cork** | Validation constraints derived from the Essence. |
|
|
97
|
+
| **Tasting Notes** | Append-only changelog of decisions and iterations. |
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## The Essence File
|
|
102
|
+
|
|
103
|
+
Location: `decantr.essence.json` (project root, generated during CLARIFY stage).
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"$schema": "https://decantr.ai/schemas/essence.v1.json",
|
|
108
|
+
"version": "1.0.0",
|
|
109
|
+
"terroir": "saas-dashboard",
|
|
110
|
+
"vintage": {
|
|
111
|
+
"style": "command-center",
|
|
112
|
+
"mode": "dark",
|
|
113
|
+
"recipe": "command-center",
|
|
114
|
+
"shape": "sharp"
|
|
115
|
+
},
|
|
116
|
+
"character": ["tactical", "data-dense", "operational"],
|
|
117
|
+
"vessel": {
|
|
118
|
+
"type": "spa",
|
|
119
|
+
"routing": "hash"
|
|
120
|
+
},
|
|
121
|
+
"structure": [
|
|
122
|
+
{
|
|
123
|
+
"id": "overview",
|
|
124
|
+
"skeleton": "sidebar-main",
|
|
125
|
+
"surface": "_flex _col _gap4 _p4 _overflow[auto] _flex1",
|
|
126
|
+
"blend": [
|
|
127
|
+
"kpi-grid",
|
|
128
|
+
"data-table",
|
|
129
|
+
{ "cols": ["activity-feed", "chart-grid"], "at": "lg" }
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"id": "alerts",
|
|
134
|
+
"skeleton": "sidebar-main",
|
|
135
|
+
"blend": [
|
|
136
|
+
"filter-sidebar",
|
|
137
|
+
"data-table",
|
|
138
|
+
"detail-panel"
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
],
|
|
142
|
+
"tannins": ["auth", "realtime-data", "notifications"],
|
|
143
|
+
"cork": {
|
|
144
|
+
"enforce_style": true,
|
|
145
|
+
"enforce_recipe": true,
|
|
146
|
+
"allowed_custom_css": false
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Essence Version Field
|
|
152
|
+
|
|
153
|
+
The `version` field (string, semver format e.g. `"1.0.0"`) tracks the evolution of the Essence. It is optional but strongly recommended:
|
|
154
|
+
|
|
155
|
+
- **Bump the patch** (`1.0.0` -> `1.0.1`) when adding pages, tannins, or adjusting blend details
|
|
156
|
+
- **Bump the minor** (`1.0.0` -> `1.1.0`) when changing structure layout, adding sections, or swapping recipes
|
|
157
|
+
- **Bump the major** (`1.0.0` -> `2.0.0`) when changing terroir, vintage style, or fundamentally altering the project identity
|
|
158
|
+
|
|
159
|
+
The `validate` command will warn if no `version` field is present to encourage adoption.
|
|
160
|
+
|
|
161
|
+
### Sectioned Essence (Multi-Domain)
|
|
162
|
+
|
|
163
|
+
For applications spanning multiple domains, the Essence supports a sectioned format. Instead of a single `terroir`, the Essence defines `sections` — each with its own terroir, vintage, structure, and tannins.
|
|
164
|
+
|
|
165
|
+
**Detection**: If `sections` array exists → sectioned mode. If `terroir` exists → simple mode.
|
|
166
|
+
|
|
167
|
+
**Simple format** (single-domain — backward compatible):
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"terroir": "saas-dashboard",
|
|
171
|
+
"vintage": { "style": "command-center", "mode": "dark", "recipe": "command-center", "shape": "sharp" },
|
|
172
|
+
"character": ["tactical", "data-dense"],
|
|
173
|
+
"vessel": { "type": "spa", "routing": "hash" },
|
|
174
|
+
"structure": [...],
|
|
175
|
+
"tannins": ["auth", "realtime-data"],
|
|
176
|
+
"cork": { "enforce_style": true }
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Sectioned format** (multi-domain):
|
|
181
|
+
```json
|
|
182
|
+
{
|
|
183
|
+
"vessel": { "type": "spa", "routing": "hash" },
|
|
184
|
+
"character": ["professional", "technical"],
|
|
185
|
+
"sections": [
|
|
186
|
+
{
|
|
187
|
+
"id": "brand",
|
|
188
|
+
"path": "/",
|
|
189
|
+
"terroir": "portfolio",
|
|
190
|
+
"vintage": { "style": "glassmorphism", "mode": "dark" },
|
|
191
|
+
"structure": [
|
|
192
|
+
{ "id": "home", "skeleton": "full-bleed", "blend": ["hero", "cta-section"] },
|
|
193
|
+
{ "id": "about", "skeleton": "top-nav-main", "blend": ["detail-header", "timeline"] }
|
|
194
|
+
],
|
|
195
|
+
"tannins": ["analytics"]
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"id": "docs",
|
|
199
|
+
"path": "/docs",
|
|
200
|
+
"terroir": "content-site",
|
|
201
|
+
"vintage": { "style": "clean", "mode": "light" },
|
|
202
|
+
"structure": [
|
|
203
|
+
{ "id": "home", "skeleton": "sidebar-main", "blend": ["category-nav", "post-list"] },
|
|
204
|
+
{ "id": "article", "skeleton": "sidebar-main", "blend": ["article-content", "table-of-contents"] }
|
|
205
|
+
],
|
|
206
|
+
"tannins": ["search", "content-state"]
|
|
207
|
+
}
|
|
208
|
+
],
|
|
209
|
+
"shared_tannins": ["auth"],
|
|
210
|
+
"cork": { "enforce_style": true, "enforce_sections": true }
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Sectioned rules:**
|
|
215
|
+
- `vessel` and `character` are project-wide (shared across sections)
|
|
216
|
+
- Each section has its own `terroir`, `vintage`, `structure`, and `tannins`
|
|
217
|
+
- `shared_tannins` are available to all sections (auth, analytics, etc.)
|
|
218
|
+
- Section-level tannins MUST NOT duplicate shared_tannins
|
|
219
|
+
- Section `path` values define the URL namespace boundary
|
|
220
|
+
- During SERVE, the LLM generates a `beforeEach` router guard that switches style/mode per section
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Archetypes
|
|
225
|
+
|
|
226
|
+
Location: `src/registry/archetypes/`
|
|
227
|
+
|
|
228
|
+
Each archetype pre-maps domain knowledge for a type of application:
|
|
229
|
+
- **Pages**: Typical views with their skeleton layouts and patterns
|
|
230
|
+
- **Tannins**: Common functional systems (auth, search, payments, etc.)
|
|
231
|
+
- **Skeletons**: Layout descriptions per page type
|
|
232
|
+
- **Suggested Vintage**: Recommended styles and modes for the domain
|
|
233
|
+
|
|
234
|
+
Available archetypes: `ecommerce`, `saas-dashboard`, `portfolio`, `content-site`, `docs-explorer`, `financial-dashboard`, `recipe-community`
|
|
235
|
+
|
|
236
|
+
The LLM reads the archetype, gets 80% of the Structure for free, then customizes based on user requirements.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Patterns
|
|
241
|
+
|
|
242
|
+
Location: `src/registry/patterns/`
|
|
243
|
+
|
|
244
|
+
Composable building blocks that archetypes reference. Each pattern describes:
|
|
245
|
+
- **Components**: Which Decantr components are used
|
|
246
|
+
- **Default Blend**: Layout, atoms, and slot descriptions
|
|
247
|
+
- **Recipe Overrides**: Per-recipe composition differences (e.g., Command Center wraps in `cc-frame`)
|
|
248
|
+
|
|
249
|
+
Patterns resolve to concrete component compositions during the DECANT stage.
|
|
250
|
+
|
|
251
|
+
### Pattern Preset Checklist
|
|
252
|
+
|
|
253
|
+
Before creating a new pattern file, check if it can be a preset on an existing pattern:
|
|
254
|
+
|
|
255
|
+
| Pattern | Available Presets |
|
|
256
|
+
|---------|------------------|
|
|
257
|
+
| `hero` | `landing`, `image-overlay`, `image-overlay-compact` |
|
|
258
|
+
| `card-grid` | `product`, `content`, `collection`, `icon` |
|
|
259
|
+
| `form-sections` | `settings`, `creation`, `structured` |
|
|
260
|
+
| `detail-header` | `standard`, `profile` |
|
|
261
|
+
|
|
262
|
+
If the desired variation shares the same grid layout, component set, and slot structure as an existing pattern but differs only in content slots, label placement, or density, add a preset instead of a new pattern file. Reference presets in blend specs:
|
|
263
|
+
```json
|
|
264
|
+
{ "pattern": "card-grid", "preset": "product", "as": "product-grid" }
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Recipes
|
|
270
|
+
|
|
271
|
+
Location: `src/registry/recipe-*.json`
|
|
272
|
+
|
|
273
|
+
Visual language composition rules for drastic visual transformations that go beyond token-level styling. A recipe describes:
|
|
274
|
+
- **Style**: Which Decantr style to activate
|
|
275
|
+
- **Decorators**: Available CSS classes (e.g., `cc-frame`, `cc-bar`)
|
|
276
|
+
- **Compositions**: Per-component examples showing how to compose standard components differently
|
|
277
|
+
|
|
278
|
+
Available recipes: `command-center`
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Cork Rules (Anti-Drift)
|
|
283
|
+
|
|
284
|
+
### Visual Drift → Vintage Lock
|
|
285
|
+
The Essence records the Vintage. The LLM applies recipe composition rules consistently.
|
|
286
|
+
|
|
287
|
+
### Architectural Drift → Structure Lock
|
|
288
|
+
New pages must be added to the Structure before generation. Skeleton assignments are enforced.
|
|
289
|
+
|
|
290
|
+
### Intent Drift → Character Lock
|
|
291
|
+
Character traits persist across sessions. "Minimal" means compact density and restraint — always.
|
|
292
|
+
|
|
293
|
+
### Enforcement
|
|
294
|
+
```
|
|
295
|
+
Before writing ANY code, read decantr.essence.json. Verify:
|
|
296
|
+
1. Style matches the Vintage
|
|
297
|
+
2. Page exists in the Structure
|
|
298
|
+
3. Composition follows the active Recipe
|
|
299
|
+
4. Density and tone match the Character
|
|
300
|
+
If a request conflicts with the Essence, flag it and ask for confirmation.
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Cork Response Protocol
|
|
304
|
+
|
|
305
|
+
For each cork rule violation type, the LLM MUST respond with a specific action. NEVER silently violate a cork rule. ALWAYS surface the conflict to the user.
|
|
306
|
+
|
|
307
|
+
| Violation Type | LLM Response |
|
|
308
|
+
|----------------|-------------|
|
|
309
|
+
| **Style mismatch** | Ask user: "Your essence specifies {X} style but you're requesting {Y}. Update essence or keep current?" Do not proceed until resolved. |
|
|
310
|
+
| **Unlisted page** | Ask user: "This page isn't in your structure. Add it to essence first?" If confirmed, add the page to the essence's `structure` array before generating code. |
|
|
311
|
+
| **Blend violation** | Warn the user that the requested layout conflicts with the page's blend spec. Propose a blend-compatible alternative that achieves the same goal within the existing spatial arrangement. |
|
|
312
|
+
| **Recipe violation** | Show the correct recipe composition from the active recipe's `compositions` and `decorators`. Explain which wrapper or decorator class should be used instead. |
|
|
313
|
+
| **Character drift** | Flag the tone mismatch: "Your essence character is [{traits}] but this request feels [{conflicting traits}]." Suggest alternatives that align with the declared character. |
|
|
314
|
+
| **Section boundary violation** (sectioned essence) | Warn that the change crosses section boundaries. Each section has its own vintage and terroir — changes must stay within the correct section. |
|
|
315
|
+
|
|
316
|
+
### Essence-Config Reconciliation
|
|
317
|
+
|
|
318
|
+
The Essence (`decantr.essence.json`) is authoritative. The config (`decantr.config.json`) is derived from it.
|
|
319
|
+
|
|
320
|
+
When the Essence is written or updated, the LLM MUST also update the config to match:
|
|
321
|
+
|
|
322
|
+
| Essence Field | Config Field |
|
|
323
|
+
|--------------|-------------|
|
|
324
|
+
| `essence.vintage.style` | `config.style` |
|
|
325
|
+
| `essence.vintage.mode` | `config.mode` |
|
|
326
|
+
| `essence.vessel.routing` | `config.router` |
|
|
327
|
+
|
|
328
|
+
**Conflict resolution**: Essence always wins. If a user manually edits `decantr.config.json` to diverge from the Essence, the LLM updates the config back to match the Essence and warns the user: "Config was out of sync with essence. Updated config.{field} from '{old}' to '{new}' to match essence."
|
|
329
|
+
|
|
330
|
+
For sectioned essences, the config reflects the first section's vintage (the primary visual identity). If sections have different styles, the LLM sets the config to the first section's style and adds a comment in the generated `app.js` noting that style switching happens per-section via `setStyle()`.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## The Blend Spec
|
|
335
|
+
|
|
336
|
+
The Blend is the per-page spatial arrangement — a row-based layout tree that specifies how patterns are positioned relative to each other. It closes the gap between "what patterns go on a page" (archetypes) and "how to decorate components" (recipes).
|
|
337
|
+
|
|
338
|
+
### Schema
|
|
339
|
+
|
|
340
|
+
Two keys on each `structure[]` entry in the Essence:
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
blend : Row[] — ordered layout rows (replaces flat patterns array)
|
|
344
|
+
surface : string — container atoms for the page body (optional)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**Row types:**
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
Row = string // full-width pattern
|
|
351
|
+
| { cols: string[], at?: string } // equal-width columns
|
|
352
|
+
| { cols: string[], span: Record<string,number>, at?: string } // weighted columns
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
| Field | Type | Default | Purpose |
|
|
356
|
+
|-------|------|---------|---------|
|
|
357
|
+
| `cols` | `string[]` | — | Pattern IDs placed side-by-side |
|
|
358
|
+
| `span` | `{id: weight}` | all 1 | Relative column widths (sum = grid column count) |
|
|
359
|
+
| `at` | `string` | `"md"` | Breakpoint below which columns stack vertically |
|
|
360
|
+
| `surface` | `string` | `"_flex _col _gap4 _p4 _overflow[auto] _flex1"` | Page container atoms |
|
|
361
|
+
|
|
362
|
+
**Backward compatible**: `patterns` (flat array) still valid — interpreted as all patterns stacked full-width, one per row.
|
|
363
|
+
|
|
364
|
+
### Examples
|
|
365
|
+
|
|
366
|
+
**Dashboard Overview:**
|
|
367
|
+
```json
|
|
368
|
+
{
|
|
369
|
+
"id": "overview",
|
|
370
|
+
"skeleton": "sidebar-main",
|
|
371
|
+
"blend": [
|
|
372
|
+
"kpi-grid",
|
|
373
|
+
"data-table",
|
|
374
|
+
{ "cols": ["activity-feed", "chart-grid"], "at": "lg" }
|
|
375
|
+
]
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
**E-Commerce Catalog (asymmetric split):**
|
|
380
|
+
```json
|
|
381
|
+
{
|
|
382
|
+
"id": "catalog",
|
|
383
|
+
"skeleton": "top-nav-main",
|
|
384
|
+
"surface": "_flex _col _gap6 _p6 _ctrxl",
|
|
385
|
+
"blend": [
|
|
386
|
+
"sort-bar",
|
|
387
|
+
{ "cols": ["filter-sidebar", "product-grid"], "span": { "product-grid": 3 }, "at": "md" },
|
|
388
|
+
"pagination"
|
|
389
|
+
]
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**Content Article (3:1 split):**
|
|
394
|
+
```json
|
|
395
|
+
{
|
|
396
|
+
"id": "article",
|
|
397
|
+
"skeleton": "top-nav-main",
|
|
398
|
+
"surface": "_flex _col _gap8 _py8 _px6 _ctr",
|
|
399
|
+
"blend": [
|
|
400
|
+
{ "cols": ["article-content", "table-of-contents"], "span": { "article-content": 3 }, "at": "lg" },
|
|
401
|
+
"author-card",
|
|
402
|
+
"related-posts"
|
|
403
|
+
]
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### SERVE Algorithm
|
|
408
|
+
|
|
409
|
+
How the LLM reads and applies a Blend during code generation:
|
|
410
|
+
|
|
411
|
+
1. Read the structure entry's `blend` array
|
|
412
|
+
2. Create page container with `surface` atoms (or default `_flex _col _gap4 _p4 _overflow[auto] _flex1`)
|
|
413
|
+
3. For each row:
|
|
414
|
+
- **String**: render the pattern full-width. Use the pattern's `default_blend.atoms` for internal layout. Apply recipe overrides.
|
|
415
|
+
- **`{ cols }`**: create a grid wrapper with `_grid _gc{N} _gap4` where N = number of columns. Add responsive collapse: below `at` breakpoint, use single column. Render each pattern inside.
|
|
416
|
+
- **`{ cols, span }`**: compute total = sum of all span values (default 1 per unspecified). Grid gets `_gc{total}`. Each pattern gets `_span{weight}`.
|
|
417
|
+
4. Apply recipe wrappers to each pattern per `recipe_overrides`
|
|
418
|
+
5. Fill pattern slots with domain content
|
|
419
|
+
|
|
420
|
+
### Separation of Concerns
|
|
421
|
+
|
|
422
|
+
| Blend controls (spatial) | NOT Blend's concern |
|
|
423
|
+
|--------------------------|---------------------|
|
|
424
|
+
| Row ordering | Internal pattern layout (pattern's `default_blend`) |
|
|
425
|
+
| Column splits + weights | Recipe decoration (cc-frame, cc-bar, etc.) |
|
|
426
|
+
| Responsive collapse breakpoints | Content decisions (labels, data, icons) |
|
|
427
|
+
| Page container atoms | Skeleton structure (sidebar, nav) |
|
|
428
|
+
|
|
429
|
+
### Default Blends in Archetypes
|
|
430
|
+
|
|
431
|
+
Archetypes provide `default_blend` per page — the domain-typical spatial arrangement. During CLARIFY, the LLM copies `default_blend` into the Essence's `blend`, then customizes. Essence `blend` always wins.
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## Monochrome Palette
|
|
436
|
+
|
|
437
|
+
The `palette: 'monochrome'` personality trait in `derive.js` derives all 7 role colors from a single primary hue. Used by the Command Center style.
|
|
438
|
+
|
|
439
|
+
Derivation strategy (from primary H/S/L):
|
|
440
|
+
- accent: H+15°, S×0.8, L+8
|
|
441
|
+
- tertiary: H-15°, S×0.7, L-5
|
|
442
|
+
- success: H+10°, S×0.9, L+12
|
|
443
|
+
- warning: H-8°, S×1.1, L+5
|
|
444
|
+
- error: H-20°, S×1.2, L-3
|
|
445
|
+
- info: H+5°, S×0.6, L+15
|
|
446
|
+
|
|
447
|
+
All shifts within ±20° of base hue. Distinguishability via lightness/saturation. WCAG AA validated via `validateContrast()`.
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## Style Selection Heuristics
|
|
452
|
+
|
|
453
|
+
When the user hasn't specified a style, use these domain signals:
|
|
454
|
+
|
|
455
|
+
| Domain | Recommended Style | Mode | Shape | Reasoning |
|
|
456
|
+
|--------|------------------|------|-------|-----------|
|
|
457
|
+
| SaaS / Dashboard | `clean` or `auradecantism` | `dark` | `rounded` | Data density needs neutral chrome; dark reduces eye strain for long sessions |
|
|
458
|
+
| E-commerce | `clean` | `light` | `rounded` | Products need accurate color rendering; light mode builds trust |
|
|
459
|
+
| Portfolio / Agency | `auradecantism` or `glassmorphism` | `dark` | `rounded` | Visual impact and brand differentiation; dark mode feels premium |
|
|
460
|
+
| Content / Blog | `clean` | `auto` | `rounded` | Readability first; auto mode respects reader preference |
|
|
461
|
+
| Enterprise / Internal | `clean` | `auto` | `sharp` | Professional, familiar; sharp corners signal precision |
|
|
462
|
+
|
|
463
|
+
## Character Trait Clusters
|
|
464
|
+
|
|
465
|
+
Character traits map to spatial and motion decisions. Three clusters cover most projects:
|
|
466
|
+
|
|
467
|
+
| Cluster | Traits | Density | Section Padding | Content Gap | Motion |
|
|
468
|
+
|---------|--------|---------|-----------------|-------------|--------|
|
|
469
|
+
| **Spacious** | minimal, elegant, premium, editorial | Comfortable | `_py16`–`_py24` | `_gap6`–`_gap8` | Slow, subtle |
|
|
470
|
+
| **Balanced** | modern, professional, friendly, clean | Default | `_py8`–`_py12` | `_gap4`–`_gap6` | Standard |
|
|
471
|
+
| **Compact** | tactical, dense, technical, efficient | Dense | `_py4`–`_py6` | `_gap2`–`_gap3` | Fast, minimal |
|
|
472
|
+
|
|
473
|
+
Pick the cluster closest to the user's Character words, then use its spatial values as starting points for the Clarity profile.
|
|
474
|
+
|
|
475
|
+
## Tasting Notes
|
|
476
|
+
|
|
477
|
+
A tasting-notes file (`decantr.tasting-notes.md`) is an optional append-only session log that tracks decisions made during the Decantation Process.
|
|
478
|
+
|
|
479
|
+
### Format
|
|
480
|
+
|
|
481
|
+
```markdown
|
|
482
|
+
## [DATE] — [STAGE]
|
|
483
|
+
|
|
484
|
+
**Changes:** What was added, modified, or decided
|
|
485
|
+
**Decisions:** Key choices and their reasoning
|
|
486
|
+
**Cork:** Any Essence constraints applied or conflicts flagged
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### Rules
|
|
490
|
+
|
|
491
|
+
- **Append-only** — never edit previous entries
|
|
492
|
+
- **One entry per session** — each conversation adds at most one entry
|
|
493
|
+
- **Created during CLARIFY** — first entry documents Essence crystallization
|
|
494
|
+
- **Updated during AGE** — subsequent sessions append entries documenting drift checks and evolution
|
|
495
|
+
- **Location:** Project root, alongside `decantr.essence.json`
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
**See also:** `reference/spatial-guidelines.md`, `reference/style-system.md`, `reference/registry-consumption.md`, `reference/atoms.md`
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Dev Server Routes
|
|
2
|
+
|
|
3
|
+
The dev server (`tools/dev-server.js`) serves the development environment with HMR and import rewriting.
|
|
4
|
+
|
|
5
|
+
## Special Routes
|
|
6
|
+
|
|
7
|
+
### `GET /__decantr_hmr`
|
|
8
|
+
|
|
9
|
+
Server-Sent Events stream for hot module reload.
|
|
10
|
+
|
|
11
|
+
- Sends `data: reload` when files change
|
|
12
|
+
- Client connects via `new EventSource('/__decantr_hmr')`
|
|
13
|
+
|
|
14
|
+
### `GET /__decantr/essence`
|
|
15
|
+
|
|
16
|
+
Serves the project's `decantr.essence.json` file from the project root. Returns the project's Decantation Process essence as JSON data.
|
|
17
|
+
|
|
18
|
+
- No import rewriting applied
|
|
19
|
+
- Triggers HMR reload when the essence file changes on disk
|
|
20
|
+
|
|
21
|
+
### `GET /__decantr/registry/**`
|
|
22
|
+
|
|
23
|
+
Serves registry JSON files from `src/registry/` without import rewriting. These are data files consumed by the workbench and other tools at runtime.
|
|
24
|
+
|
|
25
|
+
- `/__decantr/registry/components.json` → `src/registry/components.json`
|
|
26
|
+
- `/__decantr/registry/patterns/index.json` → `src/registry/patterns/index.json`
|
|
27
|
+
- `/__decantr/registry/archetypes/ecommerce.json` → `src/registry/archetypes/ecommerce.json`
|
|
28
|
+
- `/__decantr/registry/atoms.json` → `src/registry/atoms.json`
|
|
29
|
+
- `/__decantr/registry/tokens.json` → `src/registry/tokens.json`
|
|
30
|
+
|
|
31
|
+
No import rewriting is applied — files are served as-is with `application/json` MIME type.
|
|
32
|
+
|
|
33
|
+
### `GET /__decantr/{module}/**`
|
|
34
|
+
|
|
35
|
+
Serves framework source files for browser import. Handles:
|
|
36
|
+
|
|
37
|
+
- `/__decantr/core/index.js` → `src/core/index.js`
|
|
38
|
+
- `/__decantr/components/index.js` → `src/components/index.js`
|
|
39
|
+
|
|
40
|
+
All JS files served through this route get import rewriting applied.
|
|
41
|
+
|
|
42
|
+
## Import Rewriting
|
|
43
|
+
|
|
44
|
+
The server rewrites bare module specifiers in JS files to browser-compatible paths:
|
|
45
|
+
|
|
46
|
+
| Source Import | Rewritten To |
|
|
47
|
+
|--------------|-------------|
|
|
48
|
+
| `from 'decantr/core'` | `from '/__decantr/core/index.js'` |
|
|
49
|
+
| `from 'decantr/state'` | `from '/__decantr/state/index.js'` |
|
|
50
|
+
| `from 'decantr/css'` | `from '/__decantr/css/index.js'` |
|
|
51
|
+
| `from 'decantr/components'` | `from '/__decantr/components/index.js'` |
|
|
52
|
+
| `from 'decantr/tags'` | `from '/__decantr/tags/index.js'` |
|
|
53
|
+
| `from 'decantr/router'` | `from '/__decantr/router/index.js'` |
|
|
54
|
+
|
|
55
|
+
Relative imports (`./`, `../`) are passed through unchanged.
|
|
56
|
+
|
|
57
|
+
## Static File Serving
|
|
58
|
+
|
|
59
|
+
- Serves files from the project's `public/` directory
|
|
60
|
+
- JS files get import rewriting applied
|
|
61
|
+
- SPA fallback: unmatched routes serve `public/index.html`
|
|
62
|
+
|
|
63
|
+
## File Watching
|
|
64
|
+
|
|
65
|
+
- Watches `src/` and `public/` for changes
|
|
66
|
+
- Accepts optional `options.watchDirs` array for watching additional directories (used by workbench)
|
|
67
|
+
|
|
68
|
+
### Component-Level HMR
|
|
69
|
+
|
|
70
|
+
The file watcher classifies each change to decide between a component-level HMR update and a full page reload:
|
|
71
|
+
|
|
72
|
+
| File Path Pattern | Message Type | Behavior |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `src/pages/*.js` | `hmr` | Re-imports and remounts the page component |
|
|
75
|
+
| `src/components/*.js` | `hmr` | Re-imports and remounts the component |
|
|
76
|
+
| `src/state/`, `src/css/`, `src/router/`, `src/app.js` | `reload` | Full page reload (infrastructure change) |
|
|
77
|
+
| `decantr.essence.json` | `reload` | Full page reload (project DNA change) |
|
|
78
|
+
| All other `src/` files | `reload` | Full page reload (safe default) |
|
|
79
|
+
|
|
80
|
+
**How it works:**
|
|
81
|
+
|
|
82
|
+
1. The SSE endpoint sends `{ "type": "hmr", "module": "/src/pages/home.js" }` for component files.
|
|
83
|
+
2. The HMR client script (injected into `index.html`) intercepts the message and re-imports the module with a cache-busting `?t=` query parameter.
|
|
84
|
+
3. `window.__d_hmr_remount(modulePath, newModule)` (registered by `src/core/index.js` in dev mode) unmounts and remounts the component.
|
|
85
|
+
4. If no remount hook is available, the client falls back to a full page reload.
|
|
86
|
+
|
|
87
|
+
**State preservation:** Module-level signals (defined in `src/state/` files) are not re-executed during HMR because only the changed component module is re-imported. Component-local signals are re-created, which is the expected behavior.
|
|
88
|
+
|
|
89
|
+
**Registration:** Pages and components can register their mount root via `globalThis.__d_hmr_register(modulePath, rootElement)` to enable targeted remounting. Without registration, HMR falls back to remounting the `#app` root.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
**See also:** `reference/build-tooling.md`, `reference/registry-consumption.md`
|