01
Get started.
How a site wears the system: name a theme, sync a release, import it as code, and let the build check the rest.
From KIT.md, sections 0, 1 and 10, rendered at every build.
02
0. Themes
Every HUBIQ site shares one core (grid, rail, type scale, motion, components, guards) and
wears one theme, which owns what makes it look like itself: its grounds, ink, text
roles, hairlines, accent and type families. hubiq.co.uk and atomiq.digital wear hubiq.
An initiative that needs its own look (TenantIQ first) gets its own theme. A cousin, not a
copy: the skeleton is shared, the skin is not. Added 23 October 2026; the reasoning is in
THEMES-PLAN.md.
Where a theme lives. themes/<name>/theme.css (the values) and themes/<name>/THEME.md
(its laws and ratios), optionally themes/<name>/components/ (below). A site names its
theme in one word in design/.hiq-theme; no file means hubiq. sync.sh copies the
theme into design/theme/ and hashes it, so an edit in the site fails the build.
The contract. A theme defines every one of these on :root, or the build fails.
| Group | Variables |
|---|---|
| Dark text and surfaces | --ink, --panel, --paper, --muted, --muted2 |
| Grounds | --ground-paper, --ground-mist, --ground-grey, --ground-grey-deep, --ground-ink, --ground-panel, --ground-forest |
| Text on light grounds | --ink-body, --ink-label, --lead-start |
| Hairlines | --line, --line2, --rule-light, --rule-dark |
| Accent | --house (the theme's leased hue), --house-2 (a second highlight; set it to var(--house) if the theme has none) |
| Type, by role | --f-head, --f-text, --f-display, --f-mono |
The names are the system's, not the theme's: --ground-forest is HUBIQ's green chapter and
another theme's coloured dark chapter. The theme's THEME.md says what each role is in
that theme. --ac stays core: it aliases --house and is overridden per surface as before.
Type families. The site loads its faces with next/font as CSS variables on <html>,
and the theme maps them to the four roles. The kit reads only the roles, never a face.
HUBIQ: --f-head and --f-text Inter Tight, --f-display Poppins, --f-mono Space Mono.
Contrast. The build computes, from the theme's own hex values, every pairing the
kit's ground classes set: each ground's heading, running text and label against the
ground at 4.5:1; --lead-start on paper and mist at 3:1; the accent as a line on ink and
forest at 3:1, and ink on the accent fill at 4.5:1. A value that is not a solid hex where
a ratio is needed fails rather than being skipped.
Adding a theme.
- Copy
themes/hubiq/tothemes/<name>/. Change the values, keeping every name. - Set
--houseto the initiative's leased hue (hiq-core-design.md, palette and leases). Keep only the palette hues the theme uses. - Write its
THEME.md: what each ground is for in this theme, its laws, its ratios. - In the site, write
<name>intodesign/.hiq-theme, sync, load its faces, and build. The guard tells you what is missing or unreadable.
Signature components. A component only one theme uses lives in
themes/<name>/components/, is synced into components/theme/ only on sites wearing that
theme, and is documented in that theme's THEME.md. When a second theme wants it, it moves
into kit/ and this file, written against the contract, never a hex.
1. Adopting the kit in a site
- The site is Next.js with
output: "export", hand-written CSS, the same stack as hubiq-web-v2. - Write
v2intodesign/.hiq-branch, and the theme's name intodesign/.hiq-theme(leave it out forhubiq). Then from the site runbash ../hiq-design-v2/sync.sh 3.1.0, naming the release it should wear (seeCHANGELOG.md); the site records it indesign/.hiq-version. Without a version it takes the worktree, which is fine on a preview and not for a live site. - Import the core as code, on the line after the theme's, at the top of
app/globals.css:@import "../design/theme/theme.css";then@import "../design/tokens.css";. Never copy theme or token values there: a copy silently wins or loses depending on order, and drifts. A site that must differ from the core says so in a:rootblock inglobals.css, with a comment saying why. - Load the faces the theme names with
next/fontas CSS variables on<html>. Forhubiq:--font-display(Poppins 700 and 800),--font-grot(Inter Tight, variable) and--font-mono(Space Mono 400 and 700). - In the root layout, import
../design/theme/theme.css, then./globals.css, then../design/kit/v2.css, then the site's own./site.css, in that order. - Add the inline head script that puts
json<html>before first paint, and the house arrival (.reveal/.arrive, the<Reveal />observer). Both are in hubiq-web-v2'sapp/layout.tsxandapp/globals.csstoday; they join the kit when the second site adopts it. Every hidden state in the kit is gated on.js, so without the script nothing is hidden, and nothing arrives either. - Add
node scripts/check-kit.mjsto thebuildscript afternext build. - Add
MotionToggle(writesdata-motion="off"on<html>). The kit honours it andprefers-reduced-motioneverywhere.
10. Changing the kit
- Edit
kit/v2.css,kit/components/or this file here, inhiq-design-v2on thev2branch. A new rule also goes inhiq-core-design.md. - A new class gets an entry in section 6 or a line in an existing one, or every site's build fails.
- Commit and push here. To release: raise
VERSION(minor for a change a site must look at, patch for a fix), add the entry toCHANGELOG.md, commit, tagv<version>and push the tag. Then runbash ../hiq-design-v2/sync.sh <version>from each site, check it, and commit there. A live site only ever wears a release.