Saora · Collection template
Design system
Everything on this page renders from the same tokens and config that drive the whole site — it is a view of the system, not a copy of it. Open the Personalise panel and watch this page restyle itself.
01
Colour tokens
Near-monochrome by design — the artwork supplies the colour. The accent is injected from site.config.json.
--paper
Paper · page ground
--paper-raised
Paper raised · cards, media wells
--ink
Ink · primary text
--ink-muted
Ink muted · captions, meta
--line
Line · hairlines, borders
--accent
Accent · from site.config.json
Curated palettes clients choose from — each remaps the same tokens:
Gesso
#F6F1E7 · #1C1814 · #B0502B
Limestone
#EFEFED · #141414 · #46605E
Umber
#14120F · #E9E2D6 · #BE9057
Porcelain
#FFFFFF · #101010 · #2F4A8C
02
Type
A fluid modular scale — ~1.2 on mobile widening to ~1.333 on desktop — set in one display face and one text face. Four curated pairings switch both via a single data attribute.
--text-display
artist name, hero
Light on water
--text-4
page titles
Light on water
--text-3
series titles
Light on water
--text-2
section headings
Light on water
--text-1
lead lines
Light on water
--text-0
body
Light on water
--text--1
meta, captions
Light on water
The pairings menu (also in the Personalise panel):
White Cube
Schibsted Grotesk + Inter
Print Room
Fraunces + Hanken Grotesk
Reading Room
Newsreader + Archivo
Catalogue
Bodoni Moda + Lora
03
Spacing
An 8px-based scale, plus fluid section rhythm (--space-section, 96–200px) and gutters that breathe with the viewport.
--space-1
4px
--space-2
8px
--space-3
16px
--space-4
24px
--space-5
40px
--space-6
64px
--space-7
96px
--space-8
144px
04
Components
Live instances, not screenshots — these are the same components the site renders, fed by the same data module. The full chrome (Header, Footer, Exhibitions, ContactForm) is on view across the demo pages.
WorkCard — the workhorse. Status drives the sold marker; the image ships in 4 widths:
05
The spreadsheet contract
The artist owns a sheet; each column maps onto one field of the typed Artwork contract in artworks.ts — the only module that knows where data comes from. Everything downstream is generated.
| Sheet column | Field | Where it surfaces |
|---|---|---|
| Title | title | Work page heading · browser tab · og:title · JSON-LD name |
| Year | year | Caption meta line · JSON-LD dateCreated |
| Medium | medium | Caption + work page details · image alt text · JSON-LD artMedium |
| Dimensions | dimensions | Work page details |
| Price | price | Price line — blank + status POA renders "Price on application" |
| Status | status | Sold dot on cards · price line logic (available / sold / poa) |
| Series | series | Series grouping + pages · prev/next stays inside the series |
| Description | description | Work page text · meta description |
| Order | order | Sort position within its series |
| Image file | image | 4 widths (480–1600) + modern formats at build · og:image · lightbox |
06
What the build automates
Quality that nobody has to remember — it is enforced by the pipeline on every build.
Responsive images
Sharp at build: widths 480 / 800 / 1200 / 1600, sizes per layout, lazy below the fold, intrinsic dimensions — zero layout shift.
Structured data
VisualArtwork JSON-LD generated per work page from the same data.
Meta + share
Titles, descriptions, canonical URLs and og:image derived from config + artwork data.
Sitemap + robots
@astrojs/sitemap and a generated robots.txt pointing at it, on every build.
Favicon
Inline SVG generated from the artist’s initial in their own palette.
Site chrome language
Every built-in label flows through one dictionary — language: en | es in config.