Build anything Bakery, consistently.
Tokens, components and rules shared by the website, the partner portal and the three Android apps. Dark is the default theme; light is fully supported. Everything here renders from the real components, so it never drifts.
web/DESIGN-SYSTEM.mdPrinciples
Dark and product-first
Charcoal surfaces, one bright green for action, generous rounded cards.
One action per screen
A single glowing primary button. Everything else is secondary or a text link.
Plain words first
Say what happens (“Accepted”), then the bakery line (“Proofing”) as flavour, never instead.
Compliance is design
What the public can see, and when, is part of every layout decision. See the rules below.
Colour
Use semantic tokens, never raw hex. Web: CSS variable or Tailwind class (bg-surface, text-leaf-ink). Android: Bakery.colors.<name>. Click a value to copy it.
Typography
Urbanist, one family for everything (400, 500, 600, 700, 800). Self-hosted: @fontsource/urbanist (self-hosted, OFL). Headings use the .heading utility (800, tight tracking).
Space, radius, elevation
A 4px grid. Cards 24px radius, buttons 16px, chips 12px. Shadows are rare: the glow belongs to the primary button only.
- glow:
0 10px 26px var(--leaf-glow)· Primary button only - float:
0 30px 80px rgb(0 0 0 / 0.45)· Phone mockups, floating sheets
Forms
Label above, filled field (bg-crumb), green focus border, error text below in ember-ink with aria-invalid and aria-describedby. Checkboxes use accent-[var(--leaf)].
Enter a South African mobile number, e.g. 082 123 4567.
Cards
Surface background, 24px radius, a 1px line border when cards sit on surface. Hover lifts the border to leaf/50.
FeatureCard
Icon tile, title, one or two sentences. Used on the marketing site.
- CheckList: green tick bullets
- Use for benefits and requirements
Icons
24×24, 2px round stroke, currentColor. Import from @/components/icons. Android has the same shapes in BakeryIcons.
Logo
The loaf mark: a loaf seen from above whose score marks fan out like a leaf. Wordmark is BAKERY in Urbanist 800 with 0.28em tracking.
- Keep clear space equal to the mark's height on every side
- Never recolour outside leaf / ink / on-leaf, stretch, outline or add effects
- Minimum size: 20px mark, 120px wordmark lock-up
Motion
Quick and springy, never decorative for long. Respect prefers-reduced-motion on web.
- fast · 160 ms · Colour and opacity changes
- medium · 280 ms · Page and sheet transitions
- slow · 480 ms · Entrances (fade + 18px rise)
- stagger · 45 ms · Delay between list items (first 10 only)
Android equivalents live in core-ui Motion.kt: pressScale, enterUp, popIn, bounceOnChange, shake, SuccessCheck, ConfettiBurst.
Compliance rules
These are hard rules. Breaking one is a bug. `npm run check:compliance` enforces the public-site rules.
The website markets Bakery to dispensaries, hosts partner login, legal pages and app downloads. Nothing else.
No product listings, strain cards, menus, prices or ordering anywhere a visitor can reach without signing in. Product art may appear only as abstract brand imagery.
A dispensary's own sales figures (calculator, dashboard mockups) are allowed inside an element with data-compliance="revenue-estimate".
Every patient-app download or call to action sits behind an explicit 18+ confirmation.
Don't promise effects or medical benefits. Speak to businesses about operations, not to consumers about use.
Every /api/v1 route except /health requires a signed-in app user. Menus and prices are served only to verified patients in the app.
/partners needs a partner session; /admin needs an admin session. Both are noindex.
Collect the minimum, say why at the point of collection, link the Privacy Notice, never log ID numbers or tokens.
Accessibility
- Text contrast ≥ 4.5:1; dark text (on-leaf) on green buttons
- Touch targets ≥ 44px; visible :focus-visible outline in leaf
- Every input has a <label>; errors use aria-invalid + aria-describedby
- Decorative art has empty alt and aria-hidden; icons beside text are aria-hidden
- Layouts work from 320px wide with no horizontal scroll
For agents
Start here when you extend Bakery.
- Read
web/DESIGN-SYSTEM.mdand fetch /design-system/tokens.json. - Reuse components from
web/src/components(ui, site, icons, logo) before writing new ones. New shared pieces go there and get a section on this page. - Use semantic tokens only. If you need a new token, add it to globals.css, design-tokens.ts and Android Color.kt together;
npm run check:tokensmust pass. - Keep public copy in
src/lib/site.ts; follow its compliance header. - Before you finish:
npm run typecheck && npm run build && npm run check:compliance.