Deployment

Branding without breaking the disclosure model

A museum, a university or a ministry running the Digital Passport will want it to look like theirs. Every visual decision on this site — colour, type scale, corner radius, content width, wordmark — is a token in @dpa/theme, so that is a configuration change rather than a fork. Use the switcher in the navigation to rebrand the page you are reading.

Why some tokens are validated and others are not

Not every colour on the page is decoration. Background, surfaces, rules, body text and the accent are chrome: change them freely, because nothing about the meaning of a passport depends on whether the page is near-black or paper-white.

The five role colours and the three coverage colours are not chrome. They tell a reader which disclosure tier they are looking at and whether a score can be trusted at all. A rebrand that quietly collapses enforcement and public into two similar blues has not restyled the site — it has introduced a disclosure bug wearing a stylesheet, and it will look completely fine to whoever shipped it.

So those eight tokens are themeable but checked. Distinctness is measured in CIELAB rather than by comparing hex values, because hex distance is a poor proxy for whether two colours look different to a person. Every theme in the repository is validated by a test, so a brand that hurts legibility fails CI instead of shipping.

RuleThresholdWhy
Body text on background4.5:1WCAG 2.2 AA for normal-size text.
Faint text on background3:1Labels and captions are still meant to be read.
Semantic colour on background3:1WCAG 1.4.11 — these are used as non-text indicators.
Separation between any two role coloursΔE 22A just-noticeable difference is around ΔE 2.3. This is set far higher because role colours are read at small size, in a table, possibly projected, by someone who is not deliberately comparing them.
Separation between coverage coloursΔE 18Confusing well-covered with structurally-uncovered inverts the meaning of the score printed next to it.

The brands in this repository

Slate

The project default. Dark, low-chroma, built for long reading and for screenshots that sit inside academic documents.

id
slate
scheme
dark
wordmark
DPA.
base type
1516.5px
text contrast
16.0:1 · faint 3.6:1
closest roles
public / owner — ΔE 29.6
validator
passes
public#5b9dd9
community#d4a556
museum#7fb069
enforcement#d97757
owner#a98bd4

Atrium

A light, high-legibility theme for gallery kiosks and printed handouts, where the surrounding room is bright and the screen cannot be.

id
atrium
scheme
light
wordmark
Atrium Collection
base type
15.517.5px
text contrast
16.4:1 · faint 4.2:1
closest roles
source-community / enforcement — ΔE 27.1
validator
passes
public#1f5c94
community#8a5a2b
museum#3d6b2c
enforcement#a63e1c
owner#5c3d8a

Campus

High-contrast and larger type, for lecture projection and for teaching the coverage argument to a room.

id
campus
scheme
dark
wordmark
DPA Teaching
base type
1618.5px
text contrast
18.6:1 · faint 5.9:1
closest roles
source-community / enforcement — ΔE 44.7
validator
passes
public#4db8ff
community#ffc247
museum#5fd97f
enforcement#ff7a4d
owner#c48cff

Live preview

This panel carries its own data-theme, so you can hold a candidate brand next to the one the rest of the page is using instead of flipping back and forth.

Deployed by a partner institution — example branding only. — preview

Atrium Collection Bura askos, terracotta

Confidence

58/100

Register coverage

structurally-uncovered

0 of 9 registers could identify this object. The score is not about the object; it is about the paperwork around it.

Disclosure tiers

publicsource communitymuseumenforcementowner
Human review required. A high score over uncovered registers cannot auto-issue at any threshold.
legal.holderIdentity withheld at this tier

Every colour, radius and type size in this panel came from atrium. No component was modified to produce it.

Adding your own

// packages/theme/src/themes/pinacoteca.ts
import { defineTheme } from "../define.js";

export const pinacoteca = defineTheme({
  id: "pinacoteca",
  label: "Pinacoteca",
  description: "House brand for a civic picture gallery.",
  colorScheme: "light",
  identity: {
    wordmark: "Brera",
    wordmarkAccent: "·",
    organisation: "Pinacoteca di Brera",
  },
  brand: { bg: "#fbfaf7", text: "#1b1a17", accent: "#8c2f39" },
});

Register it in THEMES, run pnpm --filter @dpa/theme test, then deploy with NEXT_PUBLIC_THEME=pinacoteca pnpm build:web. Anything not overridden falls back to the default, so a brand is usually three or four colours rather than a stylesheet.

The validator runs over every registered theme in the test suite. Had the palette above pushed two roles together, this page would say so and CI would be red.