Round-1 spec. Self-contained single HTML file. The goal is a generative layout engine that produces many distinct, well-composed posters from the same content, bounded by Swiss/typographic design rules so every result is defensible.
A designer types their content once (title, headline, two meta columns, footer, one optional image) and the tool rapidly generates many genuinely good poster layouts by sampling a rule-constrained space — not by hand-authoring each template, and not by blind randomness. Shuffle lands somewhere good every time. The designer can then edit any text in place, swap the image, change aspect ratio, and export a PNG.
"Done" for the user: open the file, see a poster, hit Shuffle repeatedly, and get visibly distinct, professional layouts — then export one as PNG.
Reference: existing "Swiss Grid Studio" posters (b/w, Helvetica-style, tight grid, large display headline, small meta columns, footer, numbered layout picker, aspect presets, Shuffle / Surprise, Export PNG). We are matching that look and interaction.
Key insight driving the design: pure random layouts look bad fast. The reference posters look good because they obey tight constraints. So the engine samples from a constrained space — a small set of compositional archetypes, each exposing rule-bound parameters — so every shuffle is a defensible layout, not a dice roll.
Decisions locked with the user:
- Core focus: the layout engine (variety + quality is the wow).
- Approach: generative from rules (not hand-authored templates).
- Content: full poster — title, headline, meta A, meta B, footer, one image.
- Stack: single self-contained HTML file, zero build.
swiss-grid-studio.html— the entire app (HTML + CSS + vanilla JS, no build, no external runtime deps). One file the user can double-click.
A design system (constants) + archetypes (composition strategies) + parameter sampling (the "generative" part) + a deterministic seed (so a layout number reproduces exactly).
-
Design system (fixed rules). A modular type scale (e.g. ratio ~1.5 over a base size), a spacing scale tied to the grid, a fixed grid (e.g. 12 columns, configurable gutter), two weights (regular + bold), b/w palette + one ink. These are the "good taste" guardrails — sampling never violates them.
-
Archetypes (composition strategies). ~5–6 named strategies, each a function
render(content, params, grid) -> positioned elements. Each defines where the masses go and which constraints it exposes. Initial set:- Monolith — one giant headline dominating the canvas, meta tucked in a corner.
- Split — vertical or horizontal division (image one side, type the other).
- Specimen — type-specimen treatment; headline as the hero, minimal meta.
- Stack — strong horizontal bands (title band / image band / meta band).
- Index — small title + meta-heavy grid, image as accent.
- Asymmetric — off-grid weighting using the columns (e.g. 5/7 split).
-
Parameter sampling (the generative part). For a given archetype, sample rule-bound params: which type-scale step the headline uses, column span of each block, image cell + size, alignment (flush-left/right), accent-block presence, meta placement. Sampling ranges are defined per archetype so results stay on- model. A seeded PRNG (mulberry32 or similar, ~10 lines) maps a layout number → a fixed param set, so "Layout 13" always renders identically and Shuffle just advances the seed.
-
Renderer. Maps the chosen archetype + params onto a CSS grid inside the canvas element. Pure DOM + CSS grid; no canvas/SVG needed for layout (only for export).
- Layout picker — numbered buttons (1..N) selecting a seed; active one highlighted.
- Canvas presets — 3:4, A4, 4:5, 1:1 (sets canvas aspect ratio).
- Content inputs — Title, Headline, Meta A, Meta B, Footer (textareas).
- Image — click/drop to add a photo into the layout's image slot.
- Shuffle — new random seed. Surprise — random archetype + seed.
- Export PNG — rasterize the canvas to a PNG download.
Text elements are contenteditable; editing in place updates the underlying content
model (so it survives a re-render). This is the reference's "click any text to edit"
behavior. Drag-to-reposition is out of scope for round 1 (see below).
- Layout/render: none — native CSS grid + DOM.
- PRNG: hand-written ~10 lines (mulberry32). No dep.
- PNG export: prefer a single small vendored lib (
html-to-imageorhtml2canvas) loaded via CDN<script>, since hand-rolling DOM→canvas rasterization (fonts, images, CSS) is large and error-prone. TRADEOFF noted in spec: one CDN dependency, justified because reimplementing it is far more code and worse. If offline-without-CDN matters, revisit. - Fonts: system Helvetica/Arial stack (
-apple-system, Helvetica, Arial) — no webfont dep, matches the reference's grotesque look acceptably for v1.
- Drag-to-reposition / freeform moving of elements (edit text in place only).
- Multiple images, image filters, color themes beyond b/w + single ink.
- Save/load projects, undo/redo history, export formats other than PNG.
- Custom fonts / font upload, multi-page, print bleed/crop marks.
- Persisting content across reloads (no localStorage in v1).
- Mobile-optimized layout of the tool UI (canvas itself is fine; tool chrome targets desktop).
- Very long headline → must not overflow the canvas; renderer clamps font size
(CSS
clamp/fit) or wraps within its grid cell. Test with a 60-char headline. - Empty fields → empty meta/footer/image must not leave broken gaps; layout closes up gracefully. Test with all-but-title empty.
- No image on an image-centric archetype → archetype falls back to a type-only
variant or a neutral placeholder block (never a broken
<img>). - Tall image in a wide slot / vice versa → image uses
object-fit: cover, never distorts. - Same layout number across reloads → seeded PRNG must reproduce it exactly.
- PNG export of an off-screen-scaled canvas → export must capture at the canvas's true design resolution, not the on-screen scaled size (verify pixel dimensions).
- Manual: open
swiss-grid-studio.htmldirectly in a browser (no server) — it renders a poster with the default content. - Manual: clicking Shuffle 10× yields 10 visibly distinct, non-broken layouts (no overflow, no empty gaps, no distorted images). Capture a screenshot strip.
- Manual: each numbered layout button reproduces the same layout on reload (seed determinism). Verify layout 1 and layout 13 look identical before/after a page refresh.
- Manual: editing the headline text in place persists through a Shuffle and a re-render (content model, not DOM, is source of truth).
- Manual: upload an image → it appears in the image slot with
object-fit:cover; a text-only archetype still works with no image. - Manual: Export PNG downloads a file at the canvas's true resolution for the selected aspect ratio (e.g. 3:4 → correct pixel ratio).
- Edge: 60-char headline and all-empty-but-title both render without breaking.
- Evidence to capture: a screenshot strip of ~6 shuffled layouts + one exported PNG opened to confirm fidelity.