@fugood/bricks-ctor 2.25.0-beta.12 → 2.25.0-beta.13
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/compile/index.ts +2 -0
- package/package.json +2 -2
- package/skills/bricks-design/SKILL.md +172 -45
- package/skills/bricks-design/references/architecture-truths.md +125 -0
- package/skills/bricks-design/references/avoiding-complexity.md +91 -0
- package/skills/bricks-design/references/design-critique.md +195 -0
- package/skills/bricks-design/references/design-languages.md +265 -0
- package/skills/bricks-design/references/performance.md +116 -0
- package/skills/bricks-design/references/presentation-and-slideshow.md +137 -0
- package/skills/bricks-design/references/translating-inputs.md +152 -0
- package/skills/bricks-design/references/variations-and-tweaks.md +124 -0
- package/skills/bricks-design/references/verification-toolchain.md +213 -0
- package/skills/bricks-design/references/when-the-brief-is-branded.md +284 -0
- package/skills/bricks-design/references/when-the-brief-is-vague.md +85 -0
- package/skills/bricks-design/references/workflow.md +134 -0
- package/skills/bricks-ux/SKILL.md +120 -0
- package/skills/bricks-ux/references/accessibility.md +162 -0
- package/skills/bricks-ux/references/flow-states.md +175 -0
- package/skills/bricks-ux/references/interaction-archetypes.md +189 -0
- package/skills/bricks-ux/references/monitoring-screens.md +153 -0
- package/skills/bricks-ux/references/pressable-composition.md +126 -0
- package/skills/bricks-ux/references/user-journey.md +168 -0
- package/skills/bricks-ux/references/ux-critique.md +256 -0
- package/tools/pull.ts +42 -2
- package/types/automation.ts +1 -0
- package/types/data-calc.ts +1 -0
- package/skills/bricks-design/LICENSE.txt +0 -180
package/compile/index.ts
CHANGED
|
@@ -641,6 +641,7 @@ const compileAutomationTest = (
|
|
|
641
641
|
|
|
642
642
|
return {
|
|
643
643
|
id: testId,
|
|
644
|
+
alias: test.alias,
|
|
644
645
|
title: test.title,
|
|
645
646
|
hide_short_ref: test.hideShortRef,
|
|
646
647
|
timeout: test.timeout,
|
|
@@ -1209,6 +1210,7 @@ export const compile = async (app: Application) => {
|
|
|
1209
1210
|
)
|
|
1210
1211
|
|
|
1211
1212
|
const calc: any = {
|
|
1213
|
+
alias: dataCalc.alias,
|
|
1212
1214
|
title: dataCalc.title,
|
|
1213
1215
|
description: dataCalc.description,
|
|
1214
1216
|
hide_short_ref: dataCalc.hideShortRef,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fugood/bricks-ctor",
|
|
3
|
-
"version": "2.25.0-beta.
|
|
3
|
+
"version": "2.25.0-beta.13",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"typecheck": "tsc --noEmit",
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"oxfmt": "^0.36.0"
|
|
27
27
|
},
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "c3b77c39d10f0149b943e6ab92b02cdddd6a628b"
|
|
29
29
|
}
|
|
@@ -1,66 +1,193 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: bricks-design
|
|
3
|
-
description:
|
|
4
|
-
|
|
3
|
+
description: >-
|
|
4
|
+
Visual design discipline for Applications and Subspaces — type,
|
|
5
|
+
palette, asset acquisition, design language, system commitment,
|
|
6
|
+
visual rhythm, brand. TRIGGER for visual / aesthetic / system /
|
|
7
|
+
style / brand-asset work even when the user names the surface in
|
|
8
|
+
product terms — slideshow / pitch deck / introduction / explainer
|
|
9
|
+
/ storyboard; kiosk / signage / menu board / lobby / reception /
|
|
10
|
+
wayfinding / retail / hospitality / museum / transit; translate /
|
|
11
|
+
port / rebuild from Figma / HTML / screenshot / website / PDF /
|
|
12
|
+
brand book; vague creative brief ("design something for the
|
|
13
|
+
lobby"); branded scene work; iteration on existing Subspace
|
|
14
|
+
(rework, redesign, audit visual system, tighten the type / palette
|
|
15
|
+
/ motion / rhythm). For end-to-end briefs (kiosk, dashboard,
|
|
16
|
+
interactive screen) this skill invokes in parallel with bricks-ux,
|
|
17
|
+
which carries the interaction / flow / usability layer. SKIP for
|
|
18
|
+
pure usability / flow / journey / affordance / feedback / recovery
|
|
19
|
+
/ accessibility / multilingual audits — those go to bricks-ux. SKIP
|
|
20
|
+
for single-Brick or Generator template work
|
|
21
|
+
(create-brick-or-generator), debugging or refactoring with no
|
|
22
|
+
design intent, or non-display deliverables (CLI, server, tooling).
|
|
23
|
+
Encodes architecture truths, performance and complexity guardrails,
|
|
24
|
+
input-translation rules, visual languages library, Direction
|
|
25
|
+
Advisor for vague briefs, Media Flow protocol for branded work,
|
|
26
|
+
verification toolchain (Electron preview MCP, on-device CDP,
|
|
27
|
+
Automations).
|
|
5
28
|
---
|
|
6
29
|
|
|
7
|
-
|
|
30
|
+
# BRICKS Design
|
|
8
31
|
|
|
9
|
-
|
|
32
|
+
You are a BRICKS **visual designer**. Your output is the visual surface of a runnable Subspace — the type, palette, asset, motion vocabulary, rhythm, and system commitment that makes the work read as one designed thing. Interaction shape (flows, journeys, affordance, feedback, accessibility) is the companion `bricks-ux` skill's domain; the two run in parallel on most briefs.
|
|
10
33
|
|
|
11
|
-
|
|
34
|
+
Every visual decision is downstream of the deployment — hardware, scene, network, language, brand, peripherals, watchdog. Web habits (scroll, hover, modals-as-overlays-by-default, semantic links) do not transfer; surface them as tells when input arrives in those shapes.
|
|
12
35
|
|
|
13
|
-
|
|
14
|
-
- **Purpose**: What problem does this interface solve? Who uses it? What platform(s)?
|
|
15
|
-
- **Tone**: Pick a strong direction: brutally minimal, maximalist, retro-futuristic, organic/natural, luxury/refined, playful, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. Use these for inspiration but design one true to the aesthetic.
|
|
16
|
-
- **Constraints**: Target platform (mobile, TV, desktop, kiosk), screen dimensions, accessibility needs.
|
|
17
|
-
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
|
36
|
+
The user-facing primitive is **Data** (legacy alias: Property Bank — kept in some internal action names like `PROPERTY_BANK`). Surface "Data" in your prose. Other primitives keep their names: Application, Subspace, Canvas, Brick, Generator, DataCalculation, Switch, Animation, Standby Transition, Media Flow, Automation.
|
|
18
37
|
|
|
19
|
-
|
|
38
|
+
## Priority #0 — Verify deployment context
|
|
20
39
|
|
|
21
|
-
|
|
22
|
-
- Production-grade and functional
|
|
23
|
-
- Visually striking and memorable
|
|
24
|
-
- Cohesive with a clear aesthetic point-of-view
|
|
25
|
-
- Meticulously refined in every detail
|
|
40
|
+
Before any design exploration, confirm: **hardware** (size, resolution, orientation, touch, viewing distance), **scene** (where the screen lives, what the user does), **network** (always-on / intermittent / offline), **language(s)**, **brand**, **peripherals** (camera, BLE, MQTT, NFC, payment, printer, sensors), **watchdog / fleet management**. If any of the first five is missing, stop and ask in a single batch — improvising on hardware or scene is the most expensive mistake in BRICKS work.
|
|
26
41
|
|
|
27
|
-
##
|
|
42
|
+
## Priority #0.5 — Visually inspect every reference, in full
|
|
28
43
|
|
|
29
|
-
|
|
30
|
-
Choose fonts that are beautiful, unique, and interesting. Avoid defaulting to system fonts — opt for distinctive choices that elevate the interface. Pair a characterful display font with a refined body font. Create clear typographic hierarchy through weight, size, spacing, and alignment. Use auto-scaling (`fontSizeVector`) when text should fill its container proportionally.
|
|
44
|
+
If the user supplies any reference material — a website URL, a docs site, a Figma link, an HTML project, a screenshot, an image, a PDF, a brand book, a video walkthrough, a competitor's product — you must **visually inspect every page, frame, and state of it**, not skim a text summary or rely on a markdown extraction. Translating from material you have not actually seen is the single fastest path to designs that miss obvious cues (layout rhythm, photography style, motion language, brand temperature) that no text description preserves.
|
|
31
45
|
|
|
32
|
-
|
|
33
|
-
Commit to a cohesive palette. Dominant colors with sharp accents outperform timid, evenly-distributed palettes. Use gradients for rich, atmospheric surfaces — multi-stop linear gradients create far more depth than flat fills. Use Data nodes as a shared color store for consistency across bricks.
|
|
46
|
+
Hard rule: a markdown extraction (e.g., `WebFetch`, an `llms.txt`, a `README.md`) is **not** visual inspection. It captures words and loses everything that makes the reference design-relevant. Use it only as a navigation aid — a list of pages to then visit visually.
|
|
34
47
|
|
|
35
|
-
|
|
36
|
-
Focus on high-impact moments: one well-orchestrated canvas enter with staggered standby reveals creates more delight than scattered micro-interactions. Use spring animations for natural, bouncy UI elements. Use composed animations (parallel/sequence) for coordinated entrance choreography. Reserve looping animations (`breatheStart`) for attention-drawing elements — overuse dulls their impact.
|
|
48
|
+
How to inspect, by source type:
|
|
37
49
|
|
|
38
|
-
|
|
39
|
-
|
|
50
|
+
- **Website / docs site URL** — drive a browser automation tool (browser-MCP, Playwright/Puppeteer-style MCP server, `agent-browser`-equivalent skill, or any host-provided browser tool). Visit the home page, every primary navigation entry, every page the user explicitly named, and every page that looks like it carries the brand's visual signature (hero, product, gallery, customers). Capture a full-page screenshot of each. Then read each screenshot back via the host's image-reading capability so you actually *see* it. If no browser automation is available, ask the user for screenshots before proceeding.
|
|
51
|
+
- **Figma / design-tool link** — use a Figma-MCP / design-tool MCP if available to enumerate every frame and image-export each; otherwise ask the user for PNG exports of every frame. Inspect each image.
|
|
52
|
+
- **HTML project on disk** — serve and screenshot every route via a browser tool, the same way as a public URL. Don't infer visuals from the source HTML/CSS.
|
|
53
|
+
- **PDF / brand book / slide deck** — read every page via the host's PDF-reading capability (page-by-page if the document is long). Do not summarize from a text extraction.
|
|
54
|
+
- **Local images / screenshots** — read each one via the image-reading tool.
|
|
55
|
+
- **Video walkthrough** — ask the user to provide key-frame screenshots, or to describe each state explicitly. Do not claim to "watch" a video you cannot actually frame-step.
|
|
40
56
|
|
|
41
|
-
|
|
42
|
-
Create atmosphere through layered elements rather than flat solid colors:
|
|
43
|
-
- **Gradients** with multiple color stops for rich backgrounds
|
|
44
|
-
- **Shadows** for elevation and hierarchy
|
|
45
|
-
- **Blur effects** (blur, progressive blur, liquid glass) for glass morphism on native platforms
|
|
46
|
-
- **Opacity layering** — stack semi-transparent rects for texture and depth
|
|
47
|
-
- **Border details** — per-side colors, styles, and widths for decorative framing
|
|
57
|
+
Coverage check before continuing: list — out loud, in your reply — every reference artifact and the count of pages / frames / images you actually saw. If anything is unseen, name the gap and ask. Translating from incomplete reference inspection is grounds for rework.
|
|
48
58
|
|
|
49
|
-
|
|
50
|
-
Design interactions that feel tactile and responsive:
|
|
51
|
-
- Scale/opacity animations on press for physical feedback
|
|
52
|
-
- Focus states for TV/controller navigation
|
|
53
|
-
- Outlet-driven switches for state-dependent visual changes
|
|
54
|
-
- Deliberate long-press patterns for secondary actions
|
|
59
|
+
## Workflow spine
|
|
55
60
|
|
|
56
|
-
|
|
61
|
+
Pass-based delivery, not sprint-to-finished. Full discipline in [`references/workflow.md`](references/workflow.md) (ask-vs-build heuristic, batched question playbook by axis, five passes with checkpoints).
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
63
|
+
1. **Verify deployment context** (Priority #0) and branch on input shape:
|
|
64
|
+
- Vague brief → [`references/when-the-brief-is-vague.md`](references/when-the-brief-is-vague.md) (Direction Advisor — interaction archetype × visual language × Canvas-graph shape for sequenced work).
|
|
65
|
+
- Branded brief → [`references/when-the-brief-is-branded.md`](references/when-the-brief-is-branded.md) (Media Flow protocol).
|
|
66
|
+
- Figma / HTML / screenshot input → [`references/translating-inputs.md`](references/translating-inputs.md).
|
|
67
|
+
- Presentation / slideshow / intro / explainer / storyboard → [`references/presentation-and-slideshow.md`](references/presentation-and-slideshow.md) (Canvas-graph shape decision, hero continuity).
|
|
68
|
+
2. **Pass 0** — Declare the system as a comment block at the top of the Subspace file: type scale, palette, **spacing scale in grid units**, motion vocabulary, grid stance (lean / break / breathe), hero Brick ids. The grid substrate is given by the runtime (Truth #6); the design decisions sit on top.
|
|
69
|
+
3. **Pass 1 — Showcase Canvas lockdown.** Build one Canvas fully lit, verify, show the user. This is the cheapest moment to redirect; do not build the full Canvas graph before sign-off.
|
|
70
|
+
4. **Pass 2** — Build out the full Canvas graph with hero ids shared across Canvases (Truth #3 as narrative principle). Mid-review checkpoint partway through.
|
|
71
|
+
5. **Pass 3** — Polish: spacing-scale adherence, density rhythm, Standby Transition vocabulary consistent, multilingual fits.
|
|
72
|
+
6. **Variations**, if exploring options — three patterns ordered by token cost, default Pattern 1. See [`references/variations-and-tweaks.md`](references/variations-and-tweaks.md). Comparison surface is chat + source tree, not the Canvas.
|
|
73
|
+
7. **Pass 4** — Verification gate (below) + self-critique (5 dimensions + first-viewer rubric for sequenced work). Never declare done off a single screenshot.
|
|
61
74
|
|
|
62
|
-
|
|
75
|
+
## The 10 architecture truths
|
|
63
76
|
|
|
64
|
-
|
|
77
|
+
The load-bearing laws. Each is unpacked in [`references/architecture-truths.md`](references/architecture-truths.md).
|
|
65
78
|
|
|
66
|
-
|
|
79
|
+
1. **Canvas is a state, not a screen.** A Subspace is a state machine; Canvases are states; Brick events / Data changes are transitions. Treat Canvases as web pages and you'll fight the runtime.
|
|
80
|
+
2. **Data is the conduit for *dynamic* values.** Anything that varies at runtime (content, i18n, Generator inputs/outputs, Subspace boundaries, event payloads) flows through Data. Hardcoded values in genuinely-static, single-use Bricks are fine — convention is loose, not enforced. The rule kicks in the moment the value can change.
|
|
81
|
+
3. **Shared Brick ids across Canvases auto-tween.** Use the same Brick on Canvas A and Canvas B with different frames — the runtime animates position/size for free. This is the highest-leverage technique for a polished feel; rewriting per Canvas throws it away.
|
|
82
|
+
4. **Switches compare; Data Hit/Not-Hit only matches.** Canvas / Brick / Generator Switches support `==` `!=` `>` `<` `>=` `<=` against Data values (`SwitchCondData`). Data events `valueHit` / `valueNotHit` only support equal-match (`hit_equal`) or regex-match (`hit_regex`). Threshold-driven UI lives on Switches, not on Data event subscriptions. Don't confuse them.
|
|
83
|
+
5. **Generators are headless, async, event-driven.** Wire them via events; never as synchronous calls. Every chain needs a termination condition. Generators that hit hardware/network must not block the canvas thread.
|
|
84
|
+
6. **Frames are grid units.** Off-grid placement is legal but only ever intentional (overflow effects, anchor-at-origin tricks). It is never a nudge to escape the grid. Bricks fully outside the grid are auto-culled.
|
|
85
|
+
7. **Standby Transition is part of the design language.** Every visible Brick gets an entrance offset (`standbyMode` + `standbyOpacity` + `standbyDelay`); the runtime's auto-tween handles in-flight motion. Snap-cuts are reserved for emphasis (alarm states), never for routine navigation.
|
|
86
|
+
8. **Subspace is a typed module.** Inputs are call-by-value-on-host-change; outlets emit update + value-change events on the host. Extract a Subspace only when the same flow appears 2+ times or when the boundary scopes Data meaningfully — never as a "tidy up" tactic.
|
|
87
|
+
9. **DataCalculation is for derivation only.** Pure inputs → outputs (DataCalculationScript or DataCalculationMap). If your transformation has side effects, navigation, or async I/O, it belongs in an Event Action chain or a Generator. DataCalc orchestrating DataCalc is the wrong primitive.
|
|
88
|
+
10. **No scroll, no overflow, no responsive reflow.** Frames are fixed; what doesn't fit doesn't show. Design within the Canvas; don't import web habits.
|
|
89
|
+
|
|
90
|
+
## Commit to a design language
|
|
91
|
+
|
|
92
|
+
A BRICKS Application that doesn't commit to a design language reads as generic regardless of how well it runs. After Direction Advisor (or directly, when the brief is concrete enough), pick a visual language from [`references/design-languages.md`](references/design-languages.md) — Swiss Editorial / Kenya Hara emptiness / Field.io motion poetics / Brutalist web / Y2K futurist-retro / etc. — and write its system declaration as a comment block at the top of the Subspace file. Every subsequent choice cites the block; adding a value not in the block requires updating the block first. That's what makes the system structural rather than aspirational.
|
|
93
|
+
|
|
94
|
+
The commitment principle: when unsure, do *more* of what defines the chosen language, not less. A style executed at 30% reads as hesitant; at 80% it reads as deliberate. Soften signature moves and you've abandoned the language for nowhere.
|
|
95
|
+
|
|
96
|
+
The picked language is orthogonal to the picked **interaction archetype** (glance / browse / interact / transact / monitor / dwell — see [`references/when-the-brief-is-vague.md`](references/when-the-brief-is-vague.md)). Together they define the work. Pick both deliberately; combine awkward pairings (transact + Sagmeister, monitor + Magazine editorial) only as a deliberate brand statement, not by accident.
|
|
97
|
+
|
|
98
|
+
## Pressable composition
|
|
99
|
+
|
|
100
|
+
Composite-button wiring (where `on_press` sits, which Bricks bypass) is an interaction concern — see the companion `bricks-ux` skill's `pressable-composition.md`. The visual-design responsibility here is making pressable affordance *visually distinct*: a tile that's pressable should not look identical to a tile that's decorative. Affordance reads through the visual language; the wiring lands the press.
|
|
101
|
+
|
|
102
|
+
## Performance & complexity guardrails
|
|
103
|
+
|
|
104
|
+
Two reference files cover the second-order rules. Read them when the design is non-trivial.
|
|
105
|
+
|
|
106
|
+
- [`references/performance.md`](references/performance.md) — throttle at the Generator boundary, bound Data history explicitly, `persistData: true` is for last-known-good and idempotency keys (not transient flow state), boot Canvas must render in < 1 s using only cached/persisted Data, `renderOutOfViewport: false` for legitimate off-grid Bricks, offline-first cache + queue + status-Data on every networked Generator. **Media bound through Media Flow is preloaded to the device and is offline-safe by default — image / video / Lottie / Rive / brand reel are not "offline risk" categories. The offline wrap is for Generators fetching dynamic runtime data, not for design-time media.**
|
|
107
|
+
- [`references/avoiding-complexity.md`](references/avoiding-complexity.md) — Subspace abuse (single-instance Subspaces are usually directories), Switch fanout (4+ on one node = state machine in disguise; promote to Canvases), DataCalc chains (orchestration in the wrong primitive), animation overuse (one orchestrated entrance > scattered micro-anims; `loop` only for attention draws), Canvas inflation (each Canvas is a state the user can be stuck in).
|
|
108
|
+
|
|
109
|
+
## Asset discipline
|
|
110
|
+
|
|
111
|
+
Brand work succeeds or fails on assets, not on colors. Logo, product photography, UI screenshots, scene photography, and motion assets are first-class — colors and fonts are auxiliary. Acquire them through the protocol in [`references/when-the-brief-is-branded.md`](references/when-the-brief-is-branded.md): five steps, the 5-10-2-8 quality bar with five named scoring dimensions, three fallback paths per asset category, and structural enforcement that Bricks reference Media Flow Data via DataLink rather than embed, redraw, or skip.
|
|
112
|
+
|
|
113
|
+
When an asset category genuinely cannot be acquired and the user has no plan to provide one, the priority is: stop and ask (always for logo) → compose the host environment's image / motion generators (canvas-design / imagen / generative MCP), brand-reference-anchored, scored at the same bar → labeled placeholder with the gap tracked in `brand-spec.md`. **This skill does not duplicate generative or composition skills — it composes them.** Where the host has none, surface the constraint to the user; don't silently degrade.
|
|
114
|
+
|
|
115
|
+
## Anti-slop, terse
|
|
116
|
+
|
|
117
|
+
Snap canvas transitions on routine navigation. Hardcoded *dynamic* strings (content, i18n) bypassing Data. Hover affordances on no-touch hardware. Sketch-drawn imitations of real brand assets. Aggregator-sourced logos shipped as final. Generated brand imagery without a real brand-reference anchor. Subspaces extracted for "neatness". Switch fanout standing in for state. DataCalc chains standing in for orchestration. Animation everywhere. Stock-photo grounds behind real product photography. CSS-style scroll containers.
|
|
118
|
+
|
|
119
|
+
## Variations
|
|
120
|
+
|
|
121
|
+
When exploring options for the user to choose from, default 3, differentiated on a real axis (visual language / interaction archetype / Canvas-graph shape / motion language / content rhythm). Three colour-swap variants is not three variants.
|
|
122
|
+
|
|
123
|
+
**The comparison surface is chat + source tree, never the Canvas.** No in-Canvas palette pickers, no "choose your theme" toggles, no demo-mode switches left in production. Default to Pattern 1 (Data-preset variations — one Canvas tree, flat preset map, single-line preset switch, screenshot grid in chat). Escalate to shared module or separate Subspaces only when the variation can't be expressed by the cheaper pattern. Full protocol with token-saving discipline and knob filter in [`references/variations-and-tweaks.md`](references/variations-and-tweaks.md).
|
|
124
|
+
|
|
125
|
+
Ship a one-paragraph trade-off note alongside so the user can pick or blend with full context.
|
|
126
|
+
|
|
127
|
+
## Verification gate
|
|
128
|
+
|
|
129
|
+
**Definition of done — non-negotiable.** Before declaring a design complete, every one of the following must be true:
|
|
130
|
+
|
|
131
|
+
1. The latest source compiles cleanly (`compile` MCP).
|
|
132
|
+
2. You have produced a rendered screenshot of **every Canvas** in the deliverable via the `preview` MCP with `responseImage: true`, captured at the target hardware resolution and orientation. Cover every reachable state — Canvases gated behind events get reached by running an Automation (`testId` / `testTitleLike`).
|
|
133
|
+
3. You have **viewed** each of those screenshots back through the host's image-reading capability — not just saved them. The agent that designed the Canvas must also have seen the rendered result.
|
|
134
|
+
4. If the user supplied any reference material (Figma / website / HTML / screenshot / PDF / brand book), you have done a side-by-side visual comparison between each Canvas screenshot and the corresponding reference, and have written a short delta report listing:
|
|
135
|
+
- What matches.
|
|
136
|
+
- What intentionally diverges, and why (deployment constraint, system commitment, BRICKS-runtime limitation).
|
|
137
|
+
- What unintentionally diverges, and how you will fix it.
|
|
138
|
+
5. The verification path appropriate to the deployment has executed: Path 1 (Electron preview MCP) by default; Path 2 (on-device DevTools) when the deployment depends on real hardware behaviour, or whenever the brief touches payment, identity capture, peripherals, or LocalSync.
|
|
139
|
+
6. The browser / runtime console is clean — no 404s, no Data-key-undefined warnings, no Generator init failures.
|
|
140
|
+
|
|
141
|
+
A single hero-Canvas screenshot is **not** done. A "looks roughly like the reference" handwave is **not** done. A claim of done without screenshots in evidence is **not** done. If you have not produced and reviewed a screenshot of every Canvas, you are still mid-iteration and must say so explicitly to the user.
|
|
142
|
+
|
|
143
|
+
**Default loop — Path 1 (Electron preview, no device):**
|
|
144
|
+
|
|
145
|
+
1. `bricks-ctor` MCP `compile` — typecheck + compile gate.
|
|
146
|
+
2. `bricks-ctor` MCP `preview` with `responseImage: true` — screenshot + visual sanity. Add `testId` / `testTitleLike` to run a named Automation in the project (`brick_press`, `wait_until_canvas_change`, `assert_property`, `wait_property_update`, `match_screenshot`, ...).
|
|
147
|
+
3. Repeat step 2 for every Canvas. Single-Canvas Subspaces still require a captured + reviewed screenshot.
|
|
148
|
+
4. For sustained dev, `bun preview` exposes CDP at `localhost:19852`; drive it with `bricks devtools …` (screenshot, brick tree/query, input tap/type/key, storage data-bank, runtime eval, network list).
|
|
149
|
+
5. **Self-critique pass before declaring done** — every Canvas scored on 5 dimensions (system commitment / visual hierarchy / craft / functional fit / originality), anti-slop top-10 swept clean, < 8 scores either fixed or surfaced as accepted trade-offs. See [`references/design-critique.md`](references/design-critique.md). Verification proves it runs; critique proves it's good — both required.
|
|
150
|
+
|
|
151
|
+
**Escalate to Path 2 (device-bound DevTools)** before declaring done if the deployment depends on hardware behaviour the Electron preview cannot reproduce: physical orientation/DPI, real touch hardware, peripherals (camera/BLE/MQTT/NFC/payment/printer/sensors), watchdog cycles on the actual launcher build, LocalSync across multiple devices. **Always** Path 2 when the brief touches payment, identity capture, or peripherals.
|
|
152
|
+
|
|
153
|
+
Path 2 setup is **manual** and the agent cannot do it: ask the user to open the device's **Settings → advanced → Chrome DevTools** toggle (requires BRICKS Foundation ≥ 2.24). The device starts CDP on `:19851`. Then `bricks devtools scan` / `open` / `screenshot` / `brick …` / `input …` / `storage …` / `runtime eval` work against the device address. The device's MCP endpoint can also be bridged into Claude Code with `npx mcporter --url http://<ip>:19851/mcp --header "Authorization: Bearer <passcode>"`.
|
|
154
|
+
|
|
155
|
+
Path 3 (Remote Debugging via BRICKS Controller, off-LAN) exists for ops scenarios — out of scope for the design loop.
|
|
156
|
+
|
|
157
|
+
Full toolchain table, decision rule, and concrete invocations: [`references/verification-toolchain.md`](references/verification-toolchain.md).
|
|
158
|
+
|
|
159
|
+
## Boundaries
|
|
160
|
+
|
|
161
|
+
- Do not recreate copyrighted UIs. Build an original design that respects the IP.
|
|
162
|
+
- Do not invent brand assets. Use a labeled placeholder Brick + tracked gap list.
|
|
163
|
+
- Do not bypass Data for dynamic values.
|
|
164
|
+
- Do not carry web-frame habits across (scroll, hover, semantic links, modals-by-default, responsive reflow).
|
|
165
|
+
- Treat real-device runs as side-effecting — peripherals fire for real, payment terminals charge for real, MQTT/BLE may broadcast on shared topics. Use a staging device for verification cycles.
|
|
166
|
+
|
|
167
|
+
## Companion skill: `bricks-ux`
|
|
168
|
+
|
|
169
|
+
Interaction / flow / journey / affordance / feedback / recovery / accessibility / multilingual concerns live in `bricks-ux`. For end-to-end briefs ("design a kiosk for X", "build a presentation introducing Y") both skills invoke in parallel — `bricks-design` carries the visual layer, `bricks-ux` carries the interaction layer. Cross-references in this skill point to `bricks-ux/references/...` where the interaction discipline matters.
|
|
170
|
+
|
|
171
|
+
## Reference index
|
|
172
|
+
|
|
173
|
+
| When you need to... | Read |
|
|
174
|
+
|---|---|
|
|
175
|
+
| Decide when to ask vs build; pace the work across passes | [`references/workflow.md`](references/workflow.md) |
|
|
176
|
+
| Deepen any of the 10 truths | [`references/architecture-truths.md`](references/architecture-truths.md) |
|
|
177
|
+
| Tune for performance / offline | [`references/performance.md`](references/performance.md) |
|
|
178
|
+
| Resist over-engineering | [`references/avoiding-complexity.md`](references/avoiding-complexity.md) |
|
|
179
|
+
| Translate a Figma / HTML / screenshot | [`references/translating-inputs.md`](references/translating-inputs.md) |
|
|
180
|
+
| Pick and commit to a design language | [`references/design-languages.md`](references/design-languages.md) |
|
|
181
|
+
| Design a presentation / pitch deck / intro / explainer / slideshow (visual rhythm + hero continuity) | [`references/presentation-and-slideshow.md`](references/presentation-and-slideshow.md) |
|
|
182
|
+
| Offer variations / pick what becomes a Data knob | [`references/variations-and-tweaks.md`](references/variations-and-tweaks.md) |
|
|
183
|
+
| Self-critique on the visual dimensions | [`references/design-critique.md`](references/design-critique.md) |
|
|
184
|
+
| Verify a design before shipping | [`references/verification-toolchain.md`](references/verification-toolchain.md) |
|
|
185
|
+
| Propose visual directions for a vague brief | [`references/when-the-brief-is-vague.md`](references/when-the-brief-is-vague.md) |
|
|
186
|
+
| Acquire and bind brand assets | [`references/when-the-brief-is-branded.md`](references/when-the-brief-is-branded.md) |
|
|
187
|
+
| Compose a button so taps land where intended | `bricks-ux/references/pressable-composition.md` (companion skill) |
|
|
188
|
+
| Walk the universal interaction journey | `bricks-ux/references/user-journey.md` (companion skill) |
|
|
189
|
+
| Apply interaction-archetype rule sets | `bricks-ux/references/interaction-archetypes.md` (companion skill) |
|
|
190
|
+
| Design idle / loading / empty / error / boot / maintenance states | `bricks-ux/references/flow-states.md` (companion skill) |
|
|
191
|
+
| Design monitoring / dashboard UX | `bricks-ux/references/monitoring-screens.md` (companion skill) |
|
|
192
|
+
| Accessibility floors at deployment-relative thresholds | `bricks-ux/references/accessibility.md` (companion skill) |
|
|
193
|
+
| Tiered UX critique | `bricks-ux/references/ux-critique.md` (companion skill) |
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Architecture Truths
|
|
2
|
+
|
|
3
|
+
The 10 load-bearing laws of BRICKS design. Each one lists the truth, the runtime semantic that makes it true, and the failure mode it prevents. Re-read this when something feels arbitrary — usually one of the truths settles it.
|
|
4
|
+
|
|
5
|
+
## 1. Canvas is a state, not a screen
|
|
6
|
+
|
|
7
|
+
A Subspace is implicitly a state machine: Canvases are states, Brick events / Data changes are transitions, the visible Canvas is the current state. The runtime auto-tweens shared Bricks across Canvas changes, so transitions *are* the design language.
|
|
8
|
+
|
|
9
|
+
**Failure mode:** treating each Canvas as an independent web page. Symptoms — every Canvas redraws all chrome from scratch (no shared Bricks), transitions feel like hard cuts, navigation logic gets bolted onto Bricks instead of expressed as Canvas changes.
|
|
10
|
+
|
|
11
|
+
**Tell:** if you have one Canvas with `if-then-else` Switches toggling Brick visibility based on a `flowStep` Data, you're emulating a state machine inside one Canvas. Promote to N Canvases.
|
|
12
|
+
|
|
13
|
+
## 2. Data is the conduit for dynamic values
|
|
14
|
+
|
|
15
|
+
Anything that varies at runtime — content (text, images, URLs), i18n strings, Generator inputs/outputs, Subspace Props/Outlets, event payloads, theme tokens you want to swap — flows through Data.
|
|
16
|
+
|
|
17
|
+
Hardcoded values in genuinely-static, single-use Bricks are *fine*. The convention is loose, not enforced. A decorative Rect's `backgroundColor` set to a literal hex, a Text Brick that says `"OK"` as a confirmation label that will never change — both acceptable.
|
|
18
|
+
|
|
19
|
+
**The rule kicks in the moment the value can change.** A `"Welcome"` heading that should later support Chinese must live in Data from day one; retrofitting i18n once the design is complete is far more expensive than naming the Data key now.
|
|
20
|
+
|
|
21
|
+
**Failure mode:** Bricks coupled directly (Brick A reads Brick B's prop), Generator A invoking Generator B by name, hardcoded URLs that should be config, hardcoded English where i18n is foreseeable.
|
|
22
|
+
|
|
23
|
+
**Misread to avoid:** "dynamic values flow through Data" does not mean "media is dynamic and therefore an offline risk". Media bound through Media Flow (image / video / Lottie / Rive / brand reel via Data of `kind: media-resource-*` with `preload` metadata) is preloaded to the device at boot, integrity-verified, and served from local storage. It works offline. The offline-first concern is about Generators fetching runtime data (menus, sensor readings, LLM output, server-fed inventory), not design-time media. Don't strip rich visuals "to be safe for offline" — that's a category error.
|
|
24
|
+
|
|
25
|
+
## 3. Shared Brick ids across Canvases auto-tween
|
|
26
|
+
|
|
27
|
+
If a Brick has the same id on Canvas A and Canvas B with different `frame`s, the runtime animates `x`/`y`/`width`/`height` between the two when the Canvas changes. New Bricks enter via Standby Transition; departing Bricks exit symmetrically.
|
|
28
|
+
|
|
29
|
+
**Use it for** brand chrome (logo, header), progress indicators, persistent CTAs, status footers — anything continuous across the flow.
|
|
30
|
+
|
|
31
|
+
**Narrative principle, not just a runtime fact.** Pick one or two **hero Bricks** (logo lockup, headline word, product silhouette, brand chrome). Give them the same id across every Canvas they appear on. Each Canvas is then a *transformation* of the hero's state, not a new set of elements appearing and disappearing. Auxiliary Bricks (content that only matters to one Canvas) scope to that Canvas via Standby Transition. Heroes are the thread that makes the sequence feel like one designed thing — especially for presentation / slideshow / narrative work (see [`presentation-and-slideshow.md`](presentation-and-slideshow.md)).
|
|
32
|
+
|
|
33
|
+
**Failure mode:** every Brick is unique to its Canvas. The Application loses continuity and even with entrance/exit animations configured, every transition feels like a hard cut. This is the single biggest difference between a polished and an amateur BRICKS Application — and the difference between "narrated PowerPoint" and a designed presentation.
|
|
34
|
+
|
|
35
|
+
## 4. Switches compare; Data Hit/Not-Hit only matches
|
|
36
|
+
|
|
37
|
+
Two distinct condition systems exist; do not confuse them.
|
|
38
|
+
|
|
39
|
+
**Switches** (`SwitchDef` on Canvas / Brick / Generator) support comparison operators against `SwitchCondData`:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
method: '==' | '!=' | '>' | '<' | '>=' | '<='
|
|
43
|
+
cond: SwitchCondData | SwitchCondInnerStateCurrentCanvas | SwitchCondInnerStateOutlet
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Use Switches for threshold-driven UI: hide a Brick when `flowProgress < 1`, switch a tile's color when `value >= threshold`, show a chrome variant when the current Canvas has a specific id.
|
|
47
|
+
|
|
48
|
+
**Data events** `valueHit` / `valueNotHit` only fire on equal-match (`hit_equal: any`) or regex-match (`hit_regex: string`). They do not support `>` `<` `>=` `<=`. Use them for state notifications: "alarm.active became true", "code matched the pin regex".
|
|
49
|
+
|
|
50
|
+
**Failure mode:** trying to express `value > threshold` via a Data Hit subscription. It will not fire as you expect. Move the comparison to a Switch.
|
|
51
|
+
|
|
52
|
+
## 5. Generators are headless, async, event-driven
|
|
53
|
+
|
|
54
|
+
Generators have no visible surface. They take inputs from Data, produce outputs to Data, and are triggered by events. They emit events. They run asynchronously against the canvas thread.
|
|
55
|
+
|
|
56
|
+
**Wire them via events**, never as synchronous calls. The canonical chain: an event triggers a System / Generator Action; the Generator runs; its outlet writes to Data; downstream Data event subscribers (Bricks, other Generators, canvas-transition Actions) react.
|
|
57
|
+
|
|
58
|
+
**Every chain needs a termination condition.** Idempotency keys, guarded conditions, hard-stop counters, retry caps. Surface termination in a comment or a Switch. A Generator chain that fans out without a stop is a denial-of-service against your own Application.
|
|
59
|
+
|
|
60
|
+
**Failure mode:** synchronous "fetch then render" patterns where the canvas waits on a Generator. The runtime can render *something* immediately and let the Generator's outlet update later — design for that.
|
|
61
|
+
|
|
62
|
+
## 6. Frames are grid units
|
|
63
|
+
|
|
64
|
+
Frames (`x`, `y`, `width`, `height`) are integers in the configured grid (`layout.width` × `layout.height`; default 96 × 54 in many projects, but confirm against the actual Subspace). The runtime maps grid units to physical pixels at runtime based on hardware resolution.
|
|
65
|
+
|
|
66
|
+
Off-grid placement is *legal*: position `(-2, -3)` size `(4, 6)` puts the Brick's center at the screen origin — a real composition technique. It is *slop* when used to nudge a Brick by a non-grid amount because the grid felt restrictive.
|
|
67
|
+
|
|
68
|
+
**Bricks fully outside the grid are auto-culled** for performance. Don't rely on that as a hide mechanism — use Switches or `hidden`.
|
|
69
|
+
|
|
70
|
+
**Failure mode:** copy-pasting pixel values from a Figma render into frame fields. Translate to grid units instead.
|
|
71
|
+
|
|
72
|
+
## 7. Standby Transition is the design language
|
|
73
|
+
|
|
74
|
+
Every visible Brick item on a Canvas can declare a Standby Transition (`standbyMode`, `standbyOpacity`, `standbyDelay`, `standbyDelayRandom`, `standbyEasing`, per-property easing on x/y/width/height/opacity). On Canvas enter, the runtime animates the Brick from its standby pose to its placed pose.
|
|
75
|
+
|
|
76
|
+
Combined with shared-Brick auto-tweens (Truth #3), this is the entire transition vocabulary of a BRICKS Application. Master it.
|
|
77
|
+
|
|
78
|
+
**Snap-cuts** (no Standby) are reserved for emphasis — alarm states, error overlays, deliberate hard moments. Routine navigation that snap-cuts feels broken.
|
|
79
|
+
|
|
80
|
+
**Failure mode:** every Brick gets the same fade-in. Boring is also slop. Stagger delays, vary directions per Brick role, use the runtime's `standbyDelayRandom` for natural-looking item lists.
|
|
81
|
+
|
|
82
|
+
## 8. Subspace is a typed module
|
|
83
|
+
|
|
84
|
+
A Subspace is a self-contained mini-Application: own Canvases, own Bricks, own Generators, own Data, own DataCalculation. It binds to a host via:
|
|
85
|
+
|
|
86
|
+
- **Inputs** (Props): host-provided Data values copied into Subspace Data on host change (call-by-value at the boundary). Triggers the Subspace's `valueChange` event internally.
|
|
87
|
+
- **Outlets**: Subspace-emitted values that fire `outlet update` (always) and `outlet value change` (on diff) events in the host.
|
|
88
|
+
- **Actions / Events**: explicit host-callable actions and Subspace-emitted events.
|
|
89
|
+
|
|
90
|
+
**Extract a Subspace only when**:
|
|
91
|
+
- The same flow appears 2+ times (login, OTP, payment, language picker, confirm dialog).
|
|
92
|
+
- The boundary scopes Data meaningfully (a sub-flow with its own complete state independent of the host).
|
|
93
|
+
- A Module distribution is intended (Subspace is also the unit of reuse via the BRICKS Module system).
|
|
94
|
+
|
|
95
|
+
**Do not extract** for "tidy up". Single-instance, single-purpose Subspaces are directories, not modules; they make the design harder to reason about.
|
|
96
|
+
|
|
97
|
+
**Failure mode:** Subspaces with leaky contracts (every host Data exposed as a Prop). Tighten the contract; if you can't, the boundary is wrong.
|
|
98
|
+
|
|
99
|
+
## 9. DataCalculation is for derivation only
|
|
100
|
+
|
|
101
|
+
Two flavours: `DataCalculationScript` (a JS function with named inputs / outputs) and `DataCalculationMap` (a node-graph of `DataCommand`s with sandbox primitives — string, math, collection, datetime, color, etc.). Both are pure transformations: inputs → outputs.
|
|
102
|
+
|
|
103
|
+
**Use it for**:
|
|
104
|
+
- Format conversion (date → human-readable, currency → localized string).
|
|
105
|
+
- Combining Data values into a derived display value.
|
|
106
|
+
- Reductions / iterations over a collection.
|
|
107
|
+
- Boolean conditions feeding a Switch.
|
|
108
|
+
|
|
109
|
+
**Triggering**: `triggerMode: 'auto'` re-runs on input change (watch for circular dependencies); `'manual'` only runs on `PROPERTY_BANK_COMMAND` action.
|
|
110
|
+
|
|
111
|
+
**Do not use** for orchestration, side effects, navigation, async I/O, network calls, or anything that should be in an Event Action chain or a Generator. A DataCalc that triggers DataCalc that triggers DataCalc is an orchestration system in the wrong primitive — promote to event chains.
|
|
112
|
+
|
|
113
|
+
**Failure mode:** spinning up a Generator just to do a string concat or unit conversion. That's a DataCalc job; the inverse misuse is just as common.
|
|
114
|
+
|
|
115
|
+
## 10. No scroll, no overflow, no responsive reflow
|
|
116
|
+
|
|
117
|
+
Subspace `layout` is fixed. Frames are fixed. There is no document flow, no `overflow: scroll`, no media-query reflow. What doesn't fit, doesn't show.
|
|
118
|
+
|
|
119
|
+
**Implications**:
|
|
120
|
+
- Long content lists → `Items` Brick (interactive virtualized list) or `Slideshow` Brick (timed rotation) or paginate across Canvases.
|
|
121
|
+
- Long forms → Canvas per question, not a scrollable form.
|
|
122
|
+
- Modal dialogs → Subspace overlay or Switch-driven Brick reveal — not a popup primitive.
|
|
123
|
+
- Different orientations → different Subspaces with different `layout`s, not a single design that "responds".
|
|
124
|
+
|
|
125
|
+
**Failure mode:** importing a long Figma artboard verbatim, expecting BRICKS to scroll the overflow. Redesign the information architecture; the runtime will not save you.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Avoiding Complexity
|
|
2
|
+
|
|
3
|
+
The "designer ego" guardrails. Each one names a specific over-engineering pattern, the symptom that exposes it, and the simpler primitive it should collapse into. When in doubt, delete.
|
|
4
|
+
|
|
5
|
+
## Subspace abuse
|
|
6
|
+
|
|
7
|
+
A Subspace is a typed module — own Canvases, own Data, own Generators, own contract. It earns its complexity only when it's reused, when it scopes a non-trivial Data boundary, or when it's a distributed Module.
|
|
8
|
+
|
|
9
|
+
**Symptoms of abuse**:
|
|
10
|
+
- Single-instance Subspace whose Props are "everything in the host's Data" — not a module, a leaky directory.
|
|
11
|
+
- Subspace extracted to "tidy up" a single Canvas with 8 Bricks — the cleanup made the design harder to reason about because state now crosses a boundary.
|
|
12
|
+
- Nesting > 2 Subspaces deep — the abstraction is wrong; flatten.
|
|
13
|
+
|
|
14
|
+
**Collapse rule**: if the Subspace appears once and its Props/Outlets cover most of its Data, inline it back into the host.
|
|
15
|
+
|
|
16
|
+
## Switch fanout
|
|
17
|
+
|
|
18
|
+
Switches are powerful — they let one Brick or Canvas have several conditional poses. They become slop when used to express what should be N Canvases.
|
|
19
|
+
|
|
20
|
+
**Symptoms**:
|
|
21
|
+
- 4+ Switches on one Canvas, each gating a different subset of Bricks based on a `flowStep` Data.
|
|
22
|
+
- Switches that toggle Brick `hidden` based on the same `flowStep` value — you've hand-rolled a state machine inside one Canvas.
|
|
23
|
+
- Switch conditions referencing Outlets from a Subspace just for navigation logic.
|
|
24
|
+
|
|
25
|
+
**Collapse rule**: if the Switches partition the Canvas into more than 2 visual states gated by the same Data, promote each state to its own Canvas. Use the runtime's auto-tween of shared chrome (Truth #3) to keep continuity.
|
|
26
|
+
|
|
27
|
+
## DataCalculation chains
|
|
28
|
+
|
|
29
|
+
DataCalc is for derivation. A single calc that produces a derived value is healthy. A calc whose output triggers another calc whose output triggers another is orchestration smuggled into the wrong primitive.
|
|
30
|
+
|
|
31
|
+
**Symptoms**:
|
|
32
|
+
- DataCalc A → Data X → DataCalc B → Data Y → DataCalc C → Data Z, all `triggerMode: 'auto'`.
|
|
33
|
+
- Calcs whose names sound like verbs ("submitForm", "validateInput", "navigateNext") instead of nouns ("formattedDate", "scoreSum", "displayLabel").
|
|
34
|
+
- Circular dependency warnings or fired-multiple-times-per-update behaviour.
|
|
35
|
+
|
|
36
|
+
**Collapse rule**: derivation lives in calcs; the *flow* connecting derivations to user-visible effects lives in Event Action chains and Generators. If a calc has a side effect or triggers navigation, it shouldn't be a calc.
|
|
37
|
+
|
|
38
|
+
## Animation everywhere
|
|
39
|
+
|
|
40
|
+
Standby Transitions are part of the design language (Truth #7). `loop` animations are an emphasis tool. Reaching for animation on every Brick on every state change is noise, not polish.
|
|
41
|
+
|
|
42
|
+
**Symptoms**:
|
|
43
|
+
- Every Brick on every Canvas has a Standby spec with the same easing and duration — uniform motion is no motion.
|
|
44
|
+
- 5+ `runType: 'loop'` animations idling on a Canvas.
|
|
45
|
+
- Animations that fight each other (a parent Brick scaling while children translate against the scale).
|
|
46
|
+
|
|
47
|
+
**Collapse rule**: vary motion intentionally — stagger Standby delays per Brick role, reserve loop for genuine attention draws, use shared-Brick auto-tween instead of separate exit + entrance animations for chrome that persists.
|
|
48
|
+
|
|
49
|
+
## Canvas inflation
|
|
50
|
+
|
|
51
|
+
Each Canvas is a state. Each state is a place the user can be stuck. More Canvases is rarely better UX.
|
|
52
|
+
|
|
53
|
+
**Symptoms**:
|
|
54
|
+
- Canvases with one Brick and one event chain that immediately CHANGE_CANVAS to the next — these are state machine steps that don't deserve a Canvas.
|
|
55
|
+
- Canvases that exist only to "loadingly transition" — that's what Standby and shared-Brick tweens are for.
|
|
56
|
+
- Canvases for every locale / every theme variant — variants belong in Switches or Data-bound props, not parallel Canvases.
|
|
57
|
+
|
|
58
|
+
**Collapse rule**: a Canvas earns its existence by being a stable state the user observes for at least a moment. Transitional / loading / variant-only Canvases should fold into their neighbours.
|
|
59
|
+
|
|
60
|
+
## Generator orchestration smell
|
|
61
|
+
|
|
62
|
+
Generators are I/O units triggered by events. Generators invoking other Generators directly (via name in an Action chain that runs synchronously) is orchestration smell.
|
|
63
|
+
|
|
64
|
+
**Symptoms**:
|
|
65
|
+
- Long Action chains with `waitAsync: true` chaining 4+ Generator calls.
|
|
66
|
+
- A Generator whose only job is to call another Generator and wait.
|
|
67
|
+
- Two Generators reading and writing the same Data inside one event chain.
|
|
68
|
+
|
|
69
|
+
**Collapse rule**: split the chain at Data boundaries. Generator A writes its outlet → Data fires `valueChange` → that event chain triggers Generator B. Each piece is independently inspectable, retryable, and cacheable.
|
|
70
|
+
|
|
71
|
+
## Module overreach
|
|
72
|
+
|
|
73
|
+
The BRICKS Module system lets a Subspace be packaged with version metadata and dependency requirements (`Subspace.module`). It is a real distribution mechanism — and like any package boundary, it has a maintenance cost.
|
|
74
|
+
|
|
75
|
+
**Symptoms**:
|
|
76
|
+
- Modularizing a Subspace that's only used in one Application.
|
|
77
|
+
- Modules whose contract changes every version because the host keeps adding Props.
|
|
78
|
+
- Bumping a Module version for purely cosmetic edits.
|
|
79
|
+
|
|
80
|
+
**Collapse rule**: keep Subspaces local until at least the second consumer asks for them. Versioned modules are for genuinely shared building blocks (login, payment, OTP, language picker) maintained by someone who treats them as a product.
|
|
81
|
+
|
|
82
|
+
## "Let's make it dynamic" overreach
|
|
83
|
+
|
|
84
|
+
Truth #2 says dynamic values flow through Data. The inverse failure is making everything dynamic when it doesn't need to be — exposing every color, every text, every layout dimension as Data "in case we want to change it later".
|
|
85
|
+
|
|
86
|
+
**Symptoms**:
|
|
87
|
+
- Subspace with 40 Data entries, half of them never read by a Generator and never written by anything but a default value.
|
|
88
|
+
- Theme tokens exposed as Data even though the design ships with one theme.
|
|
89
|
+
- A Generator whose job is to "set the title" of a Brick that always says the same thing.
|
|
90
|
+
|
|
91
|
+
**Collapse rule**: Data is the conduit for *currently dynamic* values. If a value is genuinely static and single-use, hardcode it. The cost of converting later is low; the cost of carrying inert Data forever is real.
|