slotboard
v0.1.2
Published
Runtime for board layouts: JSON-in-git geometry for slots, images, shapes, paths and text, rendered as CSS container units.
Readme
slotboard
Runtime for board layouts: a JSON file in your repo holds the desktop and mobile geometry of a section — where each real component ("slot") sits, plus free-form images, shapes, lines and text — and this package renders it as CSS container units so the same layout holds at every width.
Edit the JSON visually with the board CLI (board serve <repo>), never by
hand-writing coordinates.
// vanilla
import { mountBoard } from 'slotboard'
import doc from './design/hero.board.json'
mountBoard(document.getElementById('hero'), doc, { assetBase: '/board/' })// React (SSR-safe)
import { Board } from 'slotboard/react'
import { asBoardDoc } from 'slotboard'
import json from '@/design/hero.board.json'
const doc = asBoardDoc(json) // JSON imports widen literal types; this narrows + validates
<Board doc={doc} assetBase="/board/">
<img data-board-slot="photo" … />
<div data-board-slot="card">…</div>
</Board>Rules of the road
- A slot is one of the root's descendants carrying
data-board-slot="<id>". The board sets itsleft,top,width(andz-index); its height comes from its own content unless the layer has an explicith. data-board-anchor="<name>"on an element inside a slot exposes a named anchor point (its centre) that path layers can attach to as"<slot>.<name>". Every slot also hascenter,top,bottom,left,right,tl,tr,bl,br.- Own layers (images, shapes, text, paths without a
target) are appended as the root's last children. Style slot siblings with:last-of-type/:nth-of-type, not:last-child. - Outside an active artboard (below
desktop.minWidthwith no mobile artboard) the runtime emits no rule that touches a slot — the site's own layout applies unchanged — and hides its own layers. - Image
srcvalues are bare filenames. Resolve them withassetBase(files served frompublic/) orassets(abasename -> urlmap, e.g. fromimport.meta.glob('./images/board/*', { eager: true, query: '?url', import: 'default' })when the site uses relative asset paths). - The editor bridge only activates on
localhost/127.0.0.1, inside an iframe, after a handshake from a localhost origin. Nothing editor-related ships to production beyond a ~40-line listener.
Page tweaks (editor feature, no runtime needed)
Anything on the page that is not a board slot can still be picked, nudged,
resized and restyled in board serve. Those edits are written to
src/design/tweaks.json and rendered to src/design/tweaks.css — a plain
stylesheet of selector-keyed !important overrides, split into desktop /
mobile media blocks. Import that file once (after the main stylesheet) and it
applies in production with zero JS. Treat a tweak as a note to the developer:
once the design settles, move it into the real component and delete it.
Pages without a board
The editor can still tweak any element on a page that loads the runtime. On a
page with no board, call armBridge() from slotboard once in that page's
script so the editor can connect; it is inert outside localhost.
