Module — baki.io

Module

[SCAFFOLD - Baki to revise] Every tile this site can show, all in one place

Domain
tools
Archetype
build
Audience
builder
Date

Cards

Module enablement rules

enabledModules(node) reads the frontmatter and returns the ordered list of modules that should render. Rules, in order:

  1. header - always first.
  2. launch - talks with deck_url.
  3. gallery - when gallery has entries.
  4. scene - when scene is set.
  5. pullquote - when pullquote or promise is set.
  6. metrics - when metrics has entries.
  7. process - when process has entries.
  8. widget:<name> - one per entry in widgets.
  9. cards - when cards has entries.
  10. experts - when experts has entries (Wave 3 A4).
  11. debates - when debates has entries (Wave 3 Amendment).
  12. corpus - tag nodes with a corpus.
  13. beats - when beat_layout frontmatter is present AND body has ≥1 H2 (Wave 3 D1).
  14. longform - when the MDX body is non-empty AND no beat_layout (falls back).
  15. demo - when demo_url is set (suppresses media).
  16. media - otherwise, when media_type + media_src are set.
  17. echoes - when explicit echoes exist or semantic edges resolve.

Order here is the declaration order. Column placement is decided by span:

Modules claimed by a beat via beat_layout are REMOVED from top-level scatter and nested inside BeatsModule instead. Header stays top-level always.

Beat-row layout (Wave 3 D1)

Project pages can opt into a beat-row layout via beat_layout frontmatter. When present, the MDX body’s ## Heading sections become beat rows - each row is a 2:5 CSS grid with the beat’s prose on the left (summary lane, 512px) and its assigned detail modules on the right (detail lane, 1280px), with a 64px gutter between.

beat_layout:
  Frame:      [scene, pullquote]       # prose + scene + pullquote
  Mechanism:  [process]                # prose + process steps
  The Panel:  [experts, metrics]       # prose + expert grid + metrics
  The Debates:[debates, cards]         # prose + trilemma triangles + cards
  Trace:      [gallery]                # prose + concept art
  Echoes:     [echoes]                 # prose + related content

Keys are H2 heading text (case-insensitive slug match); values are detail-module names. Supported modules: scene, pullquote, metrics, process, cards, gallery, experts, debates, media, demo, launch, echoes. Modules listed here are CLAIMED - removed from top-level scatter. Modules not listed render top-level per the legacy layout.

Beat row order = body H2 order. The outer beats module is span 8 (2048px) with canvas-frame brackets wrapping the entire row stack; each beat section inside is separated by its H2 border-bottom + a 32px vertical gap.

Inline editing (D3)

Append ?edit=1 to any file-backed page URL and - if your owner token is in localStorage under baki.owner.v1 - the canvas flips into edit mode. Click any module to select it; drag it anywhere on the canvas to reposition; edit content fields in the top-right panel. Save writes directly to the MDX file via the dev-server middleware (scripts/save-layout-middleware.mjs). No build step, no database - frontmatter is the source of truth, and visitors see the same layout and content editors do.

Two axes of edit

  1. Position - drag a module and the new (x, y) world coords land in the frontmatter’s module_positions[]. Coordinates are absolute, not deltas.
  2. Content - every editable module has a schema (src/lib/module-schemas.ts) that declares field specs. The panel renders entirely from the schema; saving patches the frontmatter keys those fields name.

The ten design rules

Full details live in the D3 inline-edit UX conventions rule in the Builder registry. Summary:

  1. Schema-driven, not UI-duplicated - register in module-schemas.ts, zero UI changes.
  2. Two storage modes - top-level frontmatter keys OR nested-array entries. A schema picks one; no mixing.
  3. Fixed widget vocabulary - text · textarea · select · color · tag-list · number. New widgets are a lib change, not a schema-local one.
  4. Amber brackets = edit signal at canvas level. Modules don’t repeat it. Only selected/dragging modules add a 1px cyan outline.
  5. Gestures - click selects, drag moves, panel-row-click selects. Double-click and long-press reserved for future use.
  6. Save is atomic per page - one POST commits modulePositions + nodeFields
    • nestedArrays + optional mdxBody. No autosave. Amber dirty badge until success.
  7. Sizing modes - content-free (frame grows padding; text, metrics) or content-anchored (content stretches to frame; gallery, scene, iframe). Resize handles respect the mode.
  8. Visitor = editor rendering - saved frontmatter drives both. No preview mode. What you see during edit is what visitors see on next reload.
  9. Field names can’t shadow - two schemas declaring the same top-level frontmatter key on the same node type fails registry validation.
  10. Array items are positional - nested-array writer patches by index. Add appends; delete collapses. Reorder is a dedicated future phase.

Module editability matrix

ModuleStorageSizingStatus
headernode-top-level (title, tagline, domain, color, archetype, audience, tech)content-freeshipped (Phase 3a canary)
pullquotenode-top-level (pullquote, promise)content-freetask 3b.2
metricsnested-array of {value, label, detail}content-freetask 3b.3
cardsnested-array of {title, body, icon, accent}content-freetask 3b.4
processnested-array of {step, detail}content-freetask 3b.5
expertsnested-array of {name, discipline, marker, position}content-freetask 3b.6
debatesnested-array of {title, top/left/right vertex, resolution}content-freetask 3b.7
echoesnode-top-level (tag-list of slugs)content-freetask 3b.8
gallerynested-array of {src, caption, beat}content-anchoredtask 3b.9
scenenode-top-level (select from scene registry)content-anchoredtask 3b.10
launchnode-top-level (deck_url, event, venue, date, status)content-anchoredtask 3b.11
widget:*node-top-level (widgets tag-list)content-freetask 3b.12
demo / medianode-top-level (demo_url OR media_type + media_src)content-anchoredtask 3b.13
longformmdx-body (the whole body after ---)content-freetask 3b.14 (special)
beat-prose:<slug>mdx-body-section (per-H2 fragment)content-freetask 3b.15 (special)
signal-drop-composeview-only (visitor writes, not author)-not editable
corpusview-only (tag-derived aggregation)-not editable
preferences / presence-dashboardsystem modules-not editable

Phases beyond 3b:

Tasks 3b.1 (nested-array infrastructure) and 3b.14 (mdx-body editor) are prerequisites for the remaining nested-array schemas and the beat-prose editor respectively. The umbrella D3 Phase 3b - Inline-edit schemas for remaining modules tracks the full fan-out.