Everything you need to build Pantri
Real files, ready to use. Logos are outlined SVG, so they render the same everywhere. Tokens come in three shapes: JSON, plain CSS variables, and a drop-in for the existing v2 Tailwind setup.
The whole kit
Wordmark
App icon and favicon
Illustration kit
Design tokens and code
Fraunces and Inter are free from Google Fonts under the SIL Open Font Licence. In Next.js, load them with next/font/google; Fraunces needs the opsz and SOFT axes.
Migrating v2 to Hearth
Hearth keeps every v2 token name. Paste globals.hearth.css over the --v2-* blocks in apps/web/src/styles/globals.css, and every component already using bg-surface-page, text-ink, bg-action or border-hairline moves to Hearth with no class changes. Then merge tailwind.hearth.ts into theme.extend for the new tokens and the Fraunces titles.
| v2 variable | Hearth name | Light | Dark |
|---|---|---|---|
--v2-surface | Paper | #FAF6F0 | #1A1511 |
--v2-surface-raised | Raised | #FFFFFF | #241D18 |
--v2-surface-sunken | Sunken | #F2ECE3 | #14100D |
--v2-hairline | Hairline | #DED4C6 | #3A3029 |
--v2-field-edge | Field edge | #8E8377 | #8F8274 |
--v2-ink | Ink | #1E1914 | #F6EFE6 |
--v2-ink-secondary | Ink 2 | #5A5047 | #C9BDB0 |
--v2-ink-tertiary | Ink 3 | #6B6157 | #A89B8C |
--v2-clay | Clay | #C4501F | #E2703F |
--v2-action | Action | #A63E14 | #EE8A5C |
--v2-action-pressed | Action pressed | #8A3310 | #F4A27C |
--v2-on-action | On action | #FFFFFF | #1E1914 |
--v2-cocoa | Cocoa | #2A211B | #0F0C0A |
--v2-saffron | Saffron | #E9B44C | #E9B44C |
--v2-sage | Sage | #6F8A5E | #7E9A6C |
--v2-favourable | Good price | #1F6F43 | #5CC48A |
--v2-unfavourable | Price rise | #B4342B | #F08A80 |
Checklist
- Swap the
--v2-*values (light and dark). - Add
field-edgeto inputs and checkboxes; stop usinghairlineas a control edge. - Move figures from JetBrains Mono to Inter 600 with
.tabular;text-row-figurebecomes 17px. - Set
text-screen-titlein Fraunces 26/30 600; retire Bricolage everywhere. - Register new
text-*sizes inextendTailwindMerge(lib/utils.ts). - Point
apps/landingat the same tokens, and ban hex literals there too. - Replace the logo, favicon and PWA icons with the files above.
tailwind.hearth.ts
// Pantri · Hearth → Tailwind theme snippet for apps/web/tailwind.config.ts
// Merge into theme.extend. Existing v2 names (surface-page, surface-raised, surface-sunken,
// hairline, ink, ink-secondary, ink-tertiary, action, favourable, unfavourable, retailer-*)
// are unchanged: their VALUES move to Hearth through globals.hearth.css. Only the keys marked
// NEW are additions. Pair with the --v2-* values in globals.hearth.css.
//
// Remember (DESIGN-V2 § foundations, point 2): every new custom text-* size must also be
// registered in extendTailwindMerge in lib/utils.ts, or cn() silently drops it.
const v2 = (name: string) => `rgb(var(--v2-${name}) / <alpha-value>)`;
export const hearthTheme = {
colors: {
// existing v2 names, values now Hearth
"surface-page": v2("surface"), // Paper #FAF6F0
"surface-raised": v2("surface-raised"), // Raised #FFFFFF
"surface-sunken": v2("surface-sunken"), // Sunken #F2ECE3
hairline: v2("hairline"), // Hairline #DED4C6 (decorative only)
ink: {
DEFAULT: v2("ink"), // Ink #1E1914
secondary: v2("ink-secondary"), // Ink 2 #5A5047
tertiary: v2("ink-tertiary"), // Ink 3 #6B6157
},
action: {
DEFAULT: v2("action"), // Action #A63E14
pressed: v2("action-pressed"), // NEW #8A3310
},
"on-action": v2("on-action"), // NEW #FFFFFF (dark: #1E1914)
favourable: v2("favourable"), // Good price #1F6F43
unfavourable: v2("unfavourable"), // Price rise #B4342B
retailer: {
coles: v2("retailer-coles"), // #C5141A
woolworths: v2("retailer-woolworths"), // #0B7A35
aldi: v2("retailer-aldi"), // #0B57B0
},
"field-edge": v2("field-edge"), // NEW #8E8377: inputs, checkboxes (3.71:1)
clay: v2("clay"), // NEW #C4501F: seed, illustration, display ≥24px only
cocoa: v2("cocoa"), // NEW #2A211B: footer, cookie banner
saffron: v2("saffron"), // NEW #E9B44C: fills behind ink, illustration
sage: v2("sage"), // NEW #6F8A5E: illustration only
},
fontFamily: {
// Replaces the Bricolage `display`/`heading` aliases. Load with next/font:
// Fraunces({ subsets: ["latin"], axes: ["opsz", "SOFT"], variable: "--font-fraunces" })
display: ["var(--font-fraunces, 'Fraunces')", "Georgia", "serif"],
heading: ["var(--font-fraunces, 'Fraunces')", "Georgia", "serif"],
sans: ["var(--font-inter, 'Inter')", "Inter", "system-ui", "sans-serif"],
// JetBrains Mono is retired for figures: use font-sans + .tabular
},
fontSize: {
"row-name": ["var(--v2-row-name-size)", { lineHeight: "1.3", fontWeight: "var(--v2-row-name-weight)" }],
"row-figure": ["1.0625rem", { lineHeight: "1.375rem", fontWeight: "600" }], // 17px Inter tabular (was 15px mono)
"row-meta": ["0.8125rem", { lineHeight: "1.125rem" }], // 13/18
"section-label": ["0.6875rem", { lineHeight: "0.875rem", letterSpacing: "0.08em", fontWeight: "600" }],
"screen-title": ["1.625rem", { lineHeight: "1.875rem", letterSpacing: "-0.015em", fontWeight: "600" }], // 26/30 Fraunces (was 22/700 Inter)
"hearth-h1": ["2rem", { lineHeight: "2.25rem", letterSpacing: "-0.02em", fontWeight: "600" }], // NEW 32/36 Fraunces
"hearth-display": ["2.75rem", { lineHeight: "2.875rem", letterSpacing: "-0.025em", fontWeight: "600" }], // NEW 44/46 Fraunces
"hearth-body": ["1rem", { lineHeight: "1.5rem" }], // NEW 16/24
},
borderRadius: {
"hearth-sm": "6px", // checkboxes, tags
"hearth-md": "12px", // buttons, inputs, cookie banner
"hearth-lg": "20px", // sheet top corners
},
minHeight: { row: "64px" },
transitionDuration: { row: "120ms", sheet: "220ms", collapse: "300ms", hero: "400ms" },
transitionTimingFunction: { hearth: "cubic-bezier(.2,.8,.2,1)" },
boxShadow: {}, // Hearth uses no shadows on rows, sections or sheets. Retire card / warm / glow.
};
// Usage in tailwind.config.ts:
// import { hearthTheme } from "./tailwind.hearth";
// theme: { extend: { ...existing, colors: { ...existing.colors, ...hearthTheme.colors }, ... } }
//
// Screen titles: className="font-display text-screen-title [font-variation-settings:'opsz'_48,'SOFT'_100,'WONK'_0]"
// Or add once in globals.css: .font-display { font-variation-settings: "opsz" 72, "SOFT" 100, "WONK" 0; }
globals.hearth.css
/* Pantri · Hearth → v2 token values for apps/web/src/styles/globals.css
* Drop-in: same --v2-* names, new values, so every component already on bg-surface-page, text-ink,
* bg-action, border-hairline etc. picks up Hearth with no class changes. New Hearth tokens are added
* under the same --v2- namespace. Channels are space-separated RGB for rgb(var(--x) / <alpha-value>). */
@layer base {
:root {
--v2-surface: 250 246 240; /* #FAF6F0 Paper */
--v2-surface-raised: 255 255 255; /* #FFFFFF Raised */
--v2-surface-sunken: 242 236 227; /* #F2ECE3 Sunken */
--v2-hairline: 222 212 198; /* #DED4C6 Hairline */
--v2-field-edge: 142 131 119; /* #8E8377 Field edge */
--v2-ink: 30 25 20; /* #1E1914 Ink */
--v2-ink-secondary: 90 80 71; /* #5A5047 Ink 2 */
--v2-ink-tertiary: 107 97 87; /* #6B6157 Ink 3 */
--v2-clay: 196 80 31; /* #C4501F Clay */
--v2-action: 166 62 20; /* #A63E14 Action */
--v2-action-pressed: 138 51 16; /* #8A3310 Action pressed */
--v2-on-action: 255 255 255; /* #FFFFFF On action */
--v2-cocoa: 42 33 27; /* #2A211B Cocoa */
--v2-saffron: 233 180 76; /* #E9B44C Saffron */
--v2-sage: 111 138 94; /* #6F8A5E Sage */
--v2-favourable: 31 111 67; /* #1F6F43 Good price */
--v2-unfavourable: 180 52 43; /* #B4342B Price rise */
--v2-retailer-coles: 197 20 26; /* #C5141A Coles */
--v2-retailer-woolworths: 11 122 53; /* #0B7A35 Woolworths */
--v2-retailer-aldi: 11 87 176; /* #0B57B0 ALDI */
--v2-row-name-size: 1.0625rem; /* 17px */
--v2-row-name-weight: 600;
}
.dark {
--v2-surface: 26 21 17; /* #1A1511 */
--v2-surface-raised: 36 29 24; /* #241D18 */
--v2-surface-sunken: 20 16 13; /* #14100D */
--v2-hairline: 58 48 41; /* #3A3029 */
--v2-field-edge: 143 130 116; /* #8F8274 */
--v2-ink: 246 239 230; /* #F6EFE6 */
--v2-ink-secondary: 201 189 176; /* #C9BDB0 */
--v2-ink-tertiary: 168 155 140; /* #A89B8C */
--v2-clay: 226 112 63; /* #E2703F */
--v2-action: 238 138 92; /* #EE8A5C */
--v2-action-pressed: 244 162 124; /* #F4A27C */
--v2-on-action: 30 25 20; /* #1E1914 */
--v2-cocoa: 15 12 10; /* #0F0C0A */
--v2-saffron: 233 180 76; /* #E9B44C */
--v2-sage: 126 154 108; /* #7E9A6C */
--v2-favourable: 92 196 138; /* #5CC48A */
--v2-unfavourable: 240 138 128; /* #F08A80 */
--v2-retailer-coles: 242 102 107; /* #F2666B */
--v2-retailer-woolworths: 63 196 107; /* #3FC46B */
--v2-retailer-aldi: 90 155 232; /* #5A9BE8 */
--v2-row-name-size: 1.125rem; /* 18px */
--v2-row-name-weight: 700;
}
}
