SaoraDesign system

Saora · Version 2.1 · October 2026

Design system

One system behind every Saora artist website. This page renders from the same tokens, components and config that build the sites, so it is a view of the system rather than a copy of it. Open the Personalise panel and the page restyles itself, values and contrast checks included.

01

Principles

Four rules that every token, component and template decision is checked against.

  1. 1

    The artwork supplies the colour.

    The interface stays near-monochrome so paintings read true. Colour is reserved for one accent, used sparingly.

  2. 2

    A frame, not a painting.

    Type and layout sit beside the work, never on it. No crops, rounded corners, shadows or overlays on artwork.

  3. 3

    Curated choices, not controls.

    Artists choose from designed pairings and palettes. Every combination is tested, so no choice can make a site worse.

  4. 4

    The sheet is the source.

    Content lives in what the artist owns. Pages, images, metadata and structured data are generated from it.

02

Colour

Six semantic tokens. Components only ever use these names, so a palette is simply a new set of values for them. The values shown are read from this page as it renders.

--paper

Paper · Page ground

 

--paper-raised

Paper raised · Cards, image wells

 

--ink

Ink · Primary text

 

--ink-muted

Ink muted · Captions, meta

 

--line

Line · Hairlines, dividers

 

--accent

Accent · Focus, links, active state

 

--error

Error · Form errors only

 

The four palettes artists choose from. Each remaps the same tokens:

Gesso

#F6F1E7 · #1C1814 · #B0502B

Limestone

#EFEFED · #141414 · #46605E

Umber

#14120F · #E9E2D6 · #BE9057

Porcelain

#FFFFFF · #101010 · #2F4A8C

03

Type

A fluid modular scale, about 1.2 on phones widening to about 1.333 on desktop, set in one display face and one text face. Sizes are parsed from tokens.css; the face and current size are read live.

--text-display

Artist name, hero

42–104px · lh 1.02

 

Light on water

--text-4

Page titles

33–54px · lh 1.1

 

Light on water

--text-3

Series titles

28–40px · lh 1.1

 

Light on water

--text-2

Section headings

23–30px · lh 1.1

 

Light on water

--text-1

Lead lines

19–23px · lh 1.5

 

Painted on location in small formats, returning to the same harbours across seasons.

--text-0

Body

16–17px · lh 1.6

 

Painted on location in small formats, returning to the same harbours across seasons.

--text--1

Meta, captions, labels

13–14px · lh 1.5

 

Painted on location in small formats, returning to the same harbours across seasons.

Four pairings, switched by one attribute on <html>:

White Cube

Schibsted Grotesk + Inter

Contemporary, gallery white walls

Print Room

Fraunces + Hanken Grotesk

Warm, editorial

Reading Room

Newsreader + Archivo

Literary, quiet

Catalogue

Bodoni Moda + Lora

Classical, auction catalogue

04

Spacing

An 8px-based scale for components. Page rhythm uses two fluid tokens instead, covered under Layout.

--space-1

4px

--space-2

8px

--space-3

16px

--space-4

24px

--space-5

40px

--space-6

64px

--space-7

96px

--space-8

144px

05

Layout

Twelve columns on desktop, one on phones. Spacing between sections and at the page edges breathes with the viewport rather than jumping at breakpoints.

--gutter

Page edges · 20–56px

--space-section

Between sections · 96–200px

48–58ch

Reading measure for bios and statements

12 columns

Collection, About and work grids

Breakpoints, widest first:

980px

Side rail and work pages fold into a single column.

860px

Twelve-column layouts collapse to one column. The most used breakpoint.

720px

The Personalise panel docks to a pill at the foot of the screen.

640px

Phone: header, hero and grids tighten their spacing and tracking.

06

Components

Live instances, not screenshots. The cards are the real component fed by the demo data; the fields and button use the production form styles in form.css. Header, footer, exhibitions and the contact form are on view across the live demo.

WorkCard. Hover lifts the image 2%; sold works carry a dot and a word:

Field states:

Default

Focus

Filled

Enter a valid email address

Error

Send button states:

Default

Hover

Keyboard focus

Sending

Work status, and where it shows:

StatusOn the cardOn the work page
AvailableNo marker. The work speaks first.Price from the sheet, plus an enquire link.
SoldAccent dot plus the word Sold, never colour alone.Sold, with the price hidden.
Price on applicationNo marker.Status poa, or a blank price, renders "Price on application".
Not for saleNo marker.Not for sale, and no enquire link.

07

Accessibility

Contrast is checked against WCAG 2.2 for every text pairing in every palette. The panel below measures the look on screen right now, so it changes when you switch palette.

The current look, measured live:

Aa

Ink on paper

Body text, headings

  

Aa

Muted on paper

Captions, meta, labels

  

Aa

Muted on raised

Text on cards and wells

  

Aa

Accent on paper

Links, focus, active

  

Aa

Error on paper

Field errors

  

Aa

Paper on ink

Send button

  

Aa

Paper on accent

Send button, hover

  

Every palette, checked at build (lowest ratio 4.55:1):

PaletteInk on paperMuted on paperMuted on raisedAccent on paperError on paperPaper on inkPaper on accent
Gesso15.67AAA4.96AA4.55AA4.63AA5.84AA15.67AAA4.63AA
Limestone16.00AAA4.99AA4.59AA5.89AA5.71AA16.00AAA5.89AA
Umber14.53AAA6.36AA5.89AA6.51AA10.68AAA14.53AAA6.51AA
Porcelain19.03AAA5.10AA4.63AA8.47AAA6.57AA19.03AAA8.47AAA

Built in, on every site:

Focus

A 2px accent outline, offset 3px, on :focus-visible only, so mouse users never see it and keyboard users always do.

Skip link

The first tab stop jumps past the navigation to the main content.

Reduced motion

With prefers-reduced-motion set, smooth scrolling, reveals and page morphs are switched off and content is simply there.

Forms

Every field has a visible label. Errors have their own colour, separate from the focus accent, a heavier underline and a written message, are announced politely and set aria-invalid.

Images

Alt text is generated from title, year and medium, so no artwork ships without a description.

Status

Sold is a dot and a word. Navigation marks the current page with an underline as well as a colour change.

08

Motion

Slow, settled and never in the way of the work. One curve and one duration cover almost everything.

--ease

cubic-bezier(0.22, 0.61, 0.36, 1)

--speed

0.45s

Press to run a move on the token curve.

Page morph

A work grows from its card into its page with a view transition, 0.45s on --ease.

Reveals

Content rises 28px and fades in over 0.9s as it enters, staggered 0.08s.

Hover

Images lift 2% over 0.7s; text colour shifts over --speed.

Scroll

Lenis smooth scrolling, light enough that the page still feels native.

Reduced motion

All of the above are off. Nothing is hidden waiting for an animation that will not run.

09

Theming

How an artist's choice becomes a styled site. Components never know which look they are in; they only read tokens.

  1. The artist picks a look

    In Saora Studio: one pairing, one palette.

  2. The build reads it

    prepare-site.mjs merges it with the site's settings file.

  3. Two hooks on <html>

    A pairing attribute and the palette's colour values. On this page right now:

    data-pairing

  4. Semantic tokens

    --paper--ink--accent--font-display and the rest take their values.

  5. Components

    WorkCard, Header, ContactForm and every layout render in the look.

On the demos, the Personalise panel rewrites the same two hooks in the browser. That is why this page restyles itself, and why a shared link reproduces a look exactly.

10

Usage and voice

The rules that keep a site looking like a gallery, and sounding like the artist.

Do

Use the accent for one job at a time: focus, the active nav item, a sold dot, a hover. Errors use their own colour.

Don’t

Use the accent for large fills, backgrounds or decoration.

Do

Show every work at its own proportions, on paper-raised if it needs a well.

Don’t

Crop, round, shadow or overlay text on an artwork.

Do

Add a new look by designing a pairing or palette that remaps the existing tokens.

Don’t

Hard-code a colour or font in a component. Everything themeable is a token.

Words, in the artist's world:

SayNot
Works, series, enquireProducts, collections, buy now
Price on applicationContact for price
SoldOut of stock
Name replies personallyOur team will get back to you

11

The content 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 columnFieldWhere it surfaces
TitletitleWork page heading · browser tab · og:title · JSON-LD name
YearyearCaption meta line · JSON-LD dateCreated
MediummediumCaption and work page details · image alt text · JSON-LD artMedium
DimensionsdimensionsWork page details
PricepricePrice line. Blank renders "Price on application"
StatusstatusSold dot on cards · price line logic (available, sold, poa, nfs)
SeriesseriesSeries grouping and pages · prev/next stays inside the series
DescriptiondescriptionWork page text · meta description
OrderorderSort position within its series
Image fileimage4 widths (480 to 1600) and modern formats at build · og:image · lightbox

12

What the build automates

Quality nobody has to remember. The pipeline enforces it on every build.

Responsive images

Sharp at build: widths 480, 800, 1200 and 1600, sizes per layout, lazy below the fold, intrinsic dimensions so nothing shifts.

Structured data

VisualArtwork JSON-LD generated for every work page from the same data.

Meta and sharing

Titles, descriptions, canonical URLs and og:image derived from config and artwork data.

Sitemap and robots

@astrojs/sitemap and a generated robots.txt pointing at it, on every build.

Favicon

An SVG generated from the artist’s initial in their own palette.

Site language

Every built-in label flows through one dictionary, English or Spanish, set in config.

13

Changelog

The system is maintained, not finished.

2.1Oct 2026

Principles, component states, live accessibility checks, motion, layout and usage documented. Form fields and the send button became shared primitives. Errors got their own colour, separate from focus. Limestone’s muted ink darkened to pass AA everywhere. Folio template added.

2.0Sep 2026

One engine for every Saora site. Looks and content come from Saora Studio, so a template is a setting, not a copy of the code.

1.1Aug 2026

The design system published as a live page.

1.0Jul 2026

Tokens, four type pairings and four palettes, switchable through the Personalise panel.