Skip to content

Site and theme

The whole file, and the settings that apply to the whole site.

The top level of site.yaml is the Site model below; every other model here is a key under it or under one of its keys.

Site

The site spec: one YAML file describes a whole site. The UI, Claude and the CLI all edit this.

A site is a nav, a list of sections and a footer. A section is either a scene (a scroll-driven visual built by a scene module: film, artwork, scene3d, sequence, parallax, type) or a block (static content: intro, features, stats, timeline, quote, cta, gallery).

Site.model_json_schema() is the contract for the UI forms and the MCP tools.

Field Type Default Description
name string required
description string ""
lang string "en"
theme Theme {} (its own defaults)
layout enum "flow" flow: sections follow one another. stack: every section is a full-screen panel with rounded top corners that slides up over the one before it.
Allowed values: "flow", "stack".
nav Nav {} (its own defaults)
loader Loader {} (its own defaults)
scroll Scroll {} (its own defaults)
sections list of one of 30 models, chosen by type: FilmScene, ArtworkScene, Scene3DScene, SequenceScene, ParallaxScene, TypeScene, VectorScene, ChartScene, MapScene, SplatScene, CodeScene, ShowroomScene, DioramaScene, InsideScene, LightScene, StagesScene, IntroBlock, FeaturesBlock, StatsBlock, TimelineBlock, QuoteBlock, CtaBlock, GalleryBlock, HeroBlock, ProductBlock, StripBlock, OrbitBlock, FaqBlock, LogosBlock, SignupBlock required
footer Footer {} (its own defaults)
pages list of Page [] Plain Markdown pages beside the site (privacy, support)
product Product (optional) null The product the site is about, declared once: takes, sequences, showroom scenes and image: {product: <view>} stills use it
trailer Trailer (optional) null A launch film built from the site's renders by studio trailer (16:9 and 9:16); {} derives the cut
video_model enum (optional) null Default video model for film beats, takes and theme.art: ltx (LTX-2.3) or wan (Wan 2.2). Unset = studio.toml's, then ltx
Allowed values: "ltx", "wan".
wan Wan {} (its own defaults) Wan 2.2 settings used wherever video_model is wan
imagery Imagery (optional) null How every generated image and film is phrased (medium, light, lens, mood, palette), so the page looks like one shoot; written by picking a direction (studio directions)
directions Directions (optional) null Brief and constraints for studio directions: several complete art directions as side-by-side boards

Theme

Field Type Default Description
preset string "night" night, brass, paper, lab, cosmos, studio, dusk, ink, blueprint, clinic (see engine/themes.yaml)
style string (optional) null An experience in one word: its own scroll mechanic, layout, transitions and look. particles, liquid-morph, holographic, neon-glow, wireframe-3d, glassmorphism, kinetic-type, isometric, clay-3d, ascii-art, gradient-mesh, comic-book, split-flap, retro-vhs, halftone, bauhaus, pixel-art, blueprint, art-deco, neo-brutalism, anime-intro, flipbook, pop-up-book, pinscreen, sand, zoetrope, stop-motion, paper-cut-out, scratch-film, smears, paint-on-glass, multiplane (see engine/styles/). Colours/fonts set here still win
mode enum (optional) null Override the preset's light/dark mode (set it when colors flip it)
Allowed values: "light", "dark".
colors map of string to string {} Override tokens: bg, bg2, ink, accent, accent2
fonts map of string to string or FontFile {} Fonts by role (display, body, mono): a Google Fonts family, or a file of the project's own ({file: fonts/Brand.woff2}), served from the site either way
display_weight integer (optional) null
display_italic_em boolean (optional) null Render <em> accent words in italic
display_em enum (optional) null How <em> words are set: accent (the accent colour, italic when display_italic_em), bold (bold italics in the text's own colour, so a headline reads as one face) or heavy (upright, the text's own colour, at the face's heaviest weight: pair with a light display_weight so emphasis is a change of weight)
Allowed values: "accent", "bold", "heavy".
labels enum (optional) null Small labels (kickers, tags, timeline dates): caps (spaced capitals in the mono face, the default) or plain (sentence case in the body face, for brands that never set all-caps)
Allowed values: "caps", "plain".
display_optical_size integer (optional) null Pin the display face's optical size (variable fonts such as Fraunces or Newsreader grow more expressive at large sizes; 36-48 keeps headlines calm)
radius string (optional) null
art Art (optional) null Artwork the style renders in its own medium (ascii-art: characters, particles: points). A prompt or a file, optionally animated
space SpaceTokens (optional) null Page spacing: gutter, max width, caption width
type TypeTokens (optional) null Type sizes: headline scale and running-text size
shade ShadeTokens (optional) null Strength of the shade over scene pictures
motion MotionTokens (optional) null Easing, how blocks arrive and how smooth scrolling follows
grain number (optional) null Film grain over the whole page: 0 none (the default) to 1; 0.15-0.3 reads as print or film
Constraints: 0 to 1.
from string or Brand (optional) null Wear a brand: a web page URL, a logo image or a brand.yaml in the project (read once and kept in .build/brand/), or the brand's tokens themselves (what studio brand writes). Its colours, fonts, radius and logo go over the preset and the style; anything else set on theme still wins
phone integer (optional) null Width in px below which the page takes its phone layout, for the stylesheet and the runtime alike. Unset keeps the built-in widths (900 for the layout, 760 for scenes, 700 for one-take pages)
Constraints: 320 to 1600.

Used in: Site.theme.

Field Type Default Description
logo string (optional) null Inline SVG path data (24x24) or an image file
links list of Link [] Empty = generated from sections with nav_label
cta Link (optional) null

Used in: Site.nav.

Loader

Loading screen: scrolling stays locked until every scene's media has loaded (videos fully downloaded, frames decoded, map tiles drawn), with a progress bar.

Field Type Default Description
enabled boolean true
label string (optional) null Text under the bar (defaults to the site name)
max_wait number 45.0 Seconds after which the site opens anyway
min_time number 0.6 Minimum seconds on screen, so it never flashes

Used in: Site.loader.

Scroll

Field Type Default Description
speed number 1.0 Pace of the smooth scroll, anchor scrolls and scroll-driven reveals: 1.2 is a fifth faster, 0.8 a fifth slower

Used in: Site.scroll.

Field Type Default Description
left string (optional) null
right string (optional) null
links list of Link [] Links shown before right, e.g. a privacy policy or terms hosted elsewhere (pages: adds its own)

Used in: Site.footer.

Page

A plain page beside the site (privacy policy, support, press): Markdown set in the site's theme, served at /<slug>/ and linked from the footer.

Field Type Default Description
slug string required URL path: 'privacy' is served at /privacy/
title string required
source string required Markdown file relative to the project folder (pages/privacy.md)
summary string (optional) null Meta description for the page
nav boolean false Also link it from the nav, after the section links

Used in: Site.pages.

Product

The product the site is about, declared once. The model is converted, fixed (axes, units), centred on its base, given its part materials and cached as one GLB; then takes (product: {}), sequences (model: product), showroom scenes and product stills (image: {product: three-quarter}) all use it, and its credit and licence go in the footer. One of model or from_photo.

Field Type Default Description
name string required Product name, e.g. 'Flipper Zero'
maker string (optional) null Who makes it, e.g. 'Flipper Devices'
url string (optional) null The maker's page for the product
model string (optional) null 3D model: GLB/glTF, OBJ, FBX, STL, PLY, STEP/STP (converted locally with OpenCascade, parts kept with their names) or 3MF; a project file or an https URL (downloaded once)
from_photo string (optional) null A cut-out PNG turned into a 3D model with TRELLIS.2 (see ProductLayer)
up enum "auto" Which axis of the file points up. auto: the format's convention (glTF, FBX and OBJ: y; STL, PLY, STEP and 3MF: z)
Allowed values: "auto", "z", "y", "x", "-z", "-y", "-x".
units enum "auto" Units the file is in. auto: metres for glTF/FBX/OBJ/PLY, millimetres for STL; STEP and 3MF carry their own; anything over 20 m is taken as millimetres
Allowed values: "auto", "m", "cm", "mm", "in", "ft".
rotation list of 3 numbers [0, 0, 0] Euler degrees applied after the up fix: turn the product so its front faces -y (the front view)
Constraints: exactly 3 items.
parts list of PartMaterial [] Material overrides by part name
exclude list of string [] Globs on part or assembly names to leave out: alternate variants stacked in one CAD file, internal parts, packaging
tessellation enum "normal" STEP: how finely curved surfaces are meshed (fine is smoother and heavier)
Allowed values: "draft", "normal", "fine".
max_triangles integer 1500000 Decimate only above this many triangles
Constraints: at least 10000.
licence string (optional) null The model's licence, e.g. 'CC BY 4.0'; shown with the credit
credit string (optional) null Attribution for the model, e.g. '3D model by Framework Computer Inc' (default: '<name> 3D model by <maker>')
concept boolean false Mark the page as a concept: the footer (and the trailer's end card) say 'Concept page. Not affiliated with <maker>.'

Used in: Site.product.

Trailer

A launch film cut by the engine from the site's own renders (studio trailer): dist/trailer/trailer-16x9.mp4, trailer-9x16.mp4 (reframed, never letterboxed) and their posters. Cuts land on a beat grid; captions and the end card are set in the theme's fonts and colours. trailer: {} derives the cut: a hook shot, the middle of the story, the product reveal, 2-4 feature callouts and an end card.

Field Type Default Description
shots list of TrailerShot [] The cut, in order. Empty: derived from the site
formats list of enum ["16x9", "9x16"] 16x9: 1920x1080; 9x16: 1080x1920 for TikTok/Reels/Shorts
Allowed values: "16x9", "9x16".
seconds number 24.0 Target length of a derived cut (15-30 s suits social)
Constraints: 8 to 90.
bpm number 100.0 Tempo of the beat grid the cuts land on
Constraints: 40 to 220.
music string (optional) null A local audio file (project path); none is generated. Without it the trailer is silent and the captions carry it
music_start number 0.0 Seconds into the music where the first cut lands (a downbeat)
Constraints: at least 0.
loudness number -14.0 Music loudness target, integrated LUFS
Constraints: -30 to -8.
fps enum 24 Allowed values: 24, 30.
captions boolean true Set captions over the shots
title string (optional) null End card name (default: the site name)
tagline string (optional) null End card line (default: the site description)
cta string (optional) null End card call to action (default: the nav button's label)
url string (optional) null End card address, e.g. stillwater.example (default: the nav button's link when it is a full URL)
disclaimer string (optional) null Small print on the end card (default: the product's concept line, 'Concept page. Not affiliated with <maker>.')
end_beats integer 8 Length of the end card on the beat grid
Constraints: 2 to 32.
end_background enum "blur" blur: the last shot, blurred under the theme colour; theme: the plain background
Allowed values: "blur", "theme".
embed boolean false Add a 'Watch the launch film' button to the first section that opens the trailer in a modal (built by studio trailer, picked up by the next build)
embed_label string "Watch the launch film" Label of the embed button

Used in: Site.trailer.

Wan

Wan 2.2 A14B settings (video_model: wan). Two 14B experts sample in turn (high-noise for the first half of the steps, low-noise for the rest). Renders at ~1280x720, 16 fps, up to 81 frames (~5 s) per clip; longer shots chain clips from the previous last frame; frames are retimed to 24 fps and restored/upscaled as usual.

Field Type Default Description
quality enum "fast" fast: the lightx2v 4-step LoRAs, cfg 1 (an 81-frame 720p clip samples in ~2.5 min on an RTX 4090, plus loading the two experts). full: no LoRAs, 20 steps at cfg 3.5 (~25 min a clip; uses the negative prompt; in tests no sharper than fast)
Allowed values: "fast", "full".
steps integer (optional) null Total steps (default 4 fast, 20 full); the high-noise expert takes the first half
Constraints: 2 to 60.
cfg number (optional) null Guidance (default 1 fast, 3.5 full)
Constraints: 1 to 10.
shift number (optional) null ModelSamplingSD3 shift (default 5 fast, 8 full)
Constraints: 1 to 20.
res list of 2 integers (optional) null Render size, multiples of 16 (default 1280x720's pixel count at the shot's aspect; 720x1280 for portrait)
Constraints: exactly 2 items.
interpolate enum "mci" 16 -> 24 fps: mci (FFmpeg motion-compensated in-betweens), blend (cross-fades) or dup (repeated frames, exact pixels, slight judder)
Allowed values: "mci", "blend", "dup".
stretch number 1.35 beats/art: a shot up to this many times one clip's length (81 frames, ~5 s) is one clip played slower instead of two chained clips (a chained clip restarts the motion)
Constraints: 1 to 2.
seed integer (optional) null takes: seed for Wan (default: the take's ltx.seed)
guide_blur number (optional) null takes: blur of the depth guide in pixels (default: ltx.guide_blur). Fun Control follows the guide's shapes closely, so a blockout box tends to stay a box: blur more (3-6) to let it paint a real table or rock, less to hold exact edges
Constraints: 0 to 12.
negative_prompt string (optional) null Used only when cfg > 1 (quality: full)

Used in: Take.wan, Site.wan.

Imagery

How every image and film this site generates is phrased, so the whole page looks like one shoot. Each part is added to every prompt the engine sends to the image and video models (a generate: image, a beat's frame and clip, a take's keyframes and segments); the prompt itself stays about the subject. Unset, nothing is added. A direction from studio directions writes this block when you pick it.

Field Type Default Description
medium string required What the picture is made of, said first: '35mm film photograph, Kodak Portra 400, fine grain', 'gouache illustration on textured paper, flat shapes'. Or a named medium, a tested recipe that also post-processes every generated still in the theme's inks so the page reads as one hand: risograph, toile, engraving, gouache, watercolour, halftone, ink
light string (optional) null The light: 'low golden-hour sun, long soft shadows', 'single window light from the left, Vermeer'
lens string (optional) null Lens and framing: '35mm, eye level, shallow depth of field'
mood string (optional) null The feeling in a few words: 'unhurried, sun-warmed, quiet'
palette string (optional) null Colour in words: 'muted terracotta, bone and sage'
inks list of string [] Named medium: the inks it prints with, #hex or theme roles (accent, accent2, ink, bg, bg2, dark). Default: the medium's own pick from the theme (risograph accent and accent2, toile accent, engraving the dark)
paper string (optional) null Named medium: the paper, #hex or a theme role. Default: the theme's background when it is pale, else a warm off-white
grain number (optional) null Named medium: how much paper and ink texture, 0 none to 1 (default: the medium's own)
Constraints: 0 to 1.
restyle boolean true Drop the medium, lens and light phrases already in a prompt ('photorealistic', 'shot on 35mm', 'golden hour') for the parts set here, so the prompt does not contradict the shoot. Off: the parts are only added

Used in: Site.imagery.

Directions

Art directions for this site (studio directions <project>): the studio's pitch. One brief in, several complete directions out (concept, palette, type, style, imagery, motion), each a board of storyboard stills side by side; pick one and it is written into this file. The writer is deterministic (curated design vocabularies combined by seed), so the same brief and seed give the same boards. Copy is never changed.

Field Type Default Description
brief string (optional) null What to pitch, in your words: 'calmer, more editorial; for people who travel slowly'. Mood words in it steer the directions
count integer 6 How many directions
Constraints: 2 to 12.
seed integer 1 Another seed, another set of directions
moods list of string [] Mood words to lean toward (calm, warm, bold, playful, technical, raw, nostalgic, futuristic, handmade, luxurious...)
keep list of enum [] Parts of the site's current look every direction must keep, varying the rest. The name and copy are always kept
Allowed values: "style", "colors", "fonts", "imagery".
styles Pool {} (its own defaults) Which styles (engine/styles/) to consider or avoid; 'none' is the default editorial layout
fonts Pool {} (its own defaults) Google Fonts families to consider or avoid
palettes PalettePool {} (its own defaults) Palettes to consider or avoid, and brand colours to carry
stills integer 4 Storyboard stills per board: the hero, then key sections
Constraints: 1 to 6.

Used in: Site.directions.