Start
Brand book
How HeyGoal looks, moves and talks — the rules every screen, file and string follows. Read this first; everything else in the system applies it.
Using the system · Content fundamentals · Visual foundations · Iconography · Logo
HeyGoal is a work dashboard for one person's practice: a multi-client freelancer first, an employee second. It covers clients, projects, tasks, time, billing (invoices, expenses, payments), notes, Quick access and a calendar. The positioning drives every rule below: the person, not the work; operations, not money; a studio you like being in, not a cockpit.
| Surface | What it is | Constraint |
|---|---|---|
| claude.ai artifact | One index.html, vanilla JS, localStorage, optional cloud copy |
The host writes data-theme on <html>, so HeyGoal themes on data-wd-theme and motion on data-motion. Never use data-theme in the app. |
| Web app (heygoal.app, Supabase) | Same source, sign-in front door, sync on by default | Phones at ≤ 860 px get a top bar and a drawer |
| Exports | Invoice and report PDFs, invoice HTML, .ics, JSON backup | PDFs are Helvetica only; print is paper-white in both themes |
Using the system
- Load
components/bundle.css. It holds the generated token block (every token on this page plus the derived accent tokens, glass, status tints and the 1.19.0 aliases) and the component and pattern CSS, written for the app's own class names (.btn,.icon-btn,.pill,.seg,.input,.check,.me,.nav…). - Set
data-wd-theme="dark"or"light"on<html>. Dark is the default. Setdata-motion="full"or"reduced"; with neither,prefers-reduced-motiondecides. - Use the semantic tokens in new work —
bg,surface,surface-2,line,line-strong,text,muted,faint,accent-text,accent-ring,on-accent,good-text… — never the ramps (neutral-*,warm-*) and never a hex literal. - The accent is a runtime choice: Settings writes
--accent: var(--<swatch>)on<html>from the 18 palette swatches (lime by default).accent-text,accent-ringandon-accentare derived from it with relative color syntax, so any swatch stays AA. Never hard-code the lime. - Icons come from
components/bundle.js:HeyGoal.ico('plus')(alsoHG_ICONS.ico) returns an inline SVG on the 20 px grid incurrentColor. - Every 1.19.0 variable still resolves through an alias (
--muted-2,--r,--pill,--display,--font,--ease,--t-fast,--t,--t-slow,--logo-ink,--logo-blue,--topbar,--topbar-blur). Aliases live for two minor versions;muted-2andr-lgare deprecated.
Content fundamentals
HeyGoal talks like a knowledgeable friend: plain words, short sentences, warm but not cute. "Hey" is the tone; "Goal" is done.
- Say what happened, then offer the way back. Destructive actions complete at once and the toast carries Undo: "Task deleted", "Payment deleted", "Demo content cleared — your own records are untouched", "Menu hidden — the button in the top-left corner brings it back". A dialog is for a choice, never a warning. The two-click erase (cloud copy, all data) is the one exception. Ctrl+Z or ⌘Z undoes while a toast with Undo shows (not inside a text field).
- Name the real state. "Saved in this browser only, until you sign in"; "Signed out. Your data stays on this device."
- One term per concept. Money words: Earned, Invoiced, Not invoiced yet, Invoiced, unpaid, Overdue, Received, Still owed. "Outstanding" is retired. The same words appear in the UI, the ? help bubbles and the PDFs.
- Errors say what happened and what to do. "That image is over 10 MB. Choose a smaller one."
- Empty states are one line, one action, text only. "No time logged yet. Start the timer or add an entry above."
- Numbers carry their unit and definition. "3 of 5 done", "day 4 of 12", a ? bubble on every money figure. Money names its currency: "US$1,200.00", "€50.00".
- Label what is not built: "Planned — not in this release".
- Sentence case everywhere; kickers are the only uppercase. Buttons start with a verb. A button that ends a form stays short ("Add client"); a call to action outside a form takes the article ("Add a client"). "Mark as paid", "Mark as sent" and "Mark as unpaid" keep the "as", and so do their toasts.
- Add or Create. "Add" puts an item in a list; "Create" makes a document. Done, Today and Not now are the only labels that aren't verbs; a page head's "New …" opens a blank record.
- Second person ("your own records"). The app never says "I" or "we".
- No emoji. Typographic characters do the work:
·separates,—comes before a consequence,→marks a range,…truncates,×closes. - No serial comma: "tasks, projects, time and billing". One form per contraction: couldn't, isn't, don't.
- Page names keep their capital inside a sentence: "Customize on Home brings it back", "Removed from Quick access".
- English only, with no reference to a country, a language or a sport. The product name is HeyGoal in every string a person reads; Workdeck-era identifiers in saved data stay as code.
- The full string library is the Microcopy section.
Visual foundations
Color
- The UI is dark first:
bgisneutral-900(#141414) withsurfaceneutral-800. The light theme is a true warm light, not an inversion:bgwarm-150(#efeee9),surfacewarm-50. - Five layers, each with one job. Neutrals carry the UI. The user accent marks selection and focus.
brand(#0080ff, the final logo blue) appears only in the top-bar tint, the front door, the favicon and the PDF stamp — never on a button. Status colors (good,warning,critical,info) mean status and nothing else, always beside a word. The palette is wayfinding. - The 18 palette swatches (
sage…coral, plusbone) color projects and clients, always with darkinktext on top. Their names are stored in saved data: never rename them. - Billing zones are fixed:
zone-invoicesamber,zone-projectperiwinkle,zone-expensespeach,zone-paymentsmint, drawn as a 3 px top strip. A zone is never a status. - Priority is an order, not a status: four strengths of one neutral (
priority-high=text,priority-medium=muted,priority-lowandpriority-backburner=faint, backburner drawn as a hollow ring), always next to its word. - Use
mutedfor secondary text (4.5:1 onbgandsurfacein both themes).faintandline-strongare for marks and control edges (3:1), never text.lineis decorative. - Use
*-texttokens for colored text (good-text,critical-text,accent-text): they are darkened on light and lifted on dark to hold 4.5:1. - Green (
live,good) marks a running timer and synced state. - On a pastel fill (tiles, project cards) use the
on-color-*tints, never a neutral:on-color-linefor dividers,on-color-surfacefor nested cards,critical-on-colorfor overdue text.
Type
- Bricolage Grotesque for display (
font-display), Inter for the UI (font-ui). Swapping a typeface is a one-line change to those two tokens. - Titles at 800 with −.035em tracking; big numbers at 800 and −.04em; body 15/1.5; buttons 600 at 14; kickers 800 at 11, uppercase, +.14em.
- Eight sizes (11, 12, 13, 14, 15, 18, 24, display) plus one big-number style. Nothing goes below 11 px.
- The big number is always tabular and sizes to its card: 15% of the card's width, from 28 to 46 px (
text-number-fit). The card setscontainer-type: inline-size; without one it renders at 46. displayis fluid in the app: clamp(32px, 4.4vw, 50px).- The ? help bubble is its own style: 700 at 12 in a 20 px circle, never uppercase or tracked. Its tip uses
note. - PDFs use Helvetica (
font-pdf) on their own point scale.
Space and layout
- A 4 px base:
space-4· 8 · 12 · 16 · 20 · 24 · 32 · 40 · 56. Lay out with gap, never margins between siblings. - Page padding is clamp(18px, 4vw, 56px).
- A glass top bar at 56 px (
topbar-height); a 248 px sidebar that collapses to a 76 px rail or hides; main content up to 1240 px; one column and a drawer at ≤ 860 px. Everything works at 390 px. - Every add-form box — input, select, date, button, color pill — is 44 px tall (
control-height). Icon buttons are 40 px and reach 44 px underpointer: coarse. - Page anatomy, in order: the title, the filters, the add form, the list.
- Home is a board of reorderable cards: six columns, tiles span two, panels three. Arrange mode uses the dashed accent frame (
accent-dash).
Corners
Six steps; pick by role, never by look.
radius-chip8: chips, filter pills, checkboxes, calendar chips and bars.radius-control10: buttons, inputs, icon buttons, menu rows, the nav highlight, and any row about 40 px tall.radius-inner12: a surface nested in a card or dialog (overview cards, stats, previews, thumbnails) and tooltips.radius-card16: panels, tiles, project cards, lists and other top-level cards.radius-floating24: dialogs, popovers, the toast, the account menu, the floating timer.radius-round: avatars and status pills.
Surfaces, borders, elevation
- Cards are flat: a
surfacefill, a 1 pxlineedge, no shadow. Home tiles and project cards are pastel fills withinktext. line-strongis the 3:1 edge for anything that identifies a control. The top-bar divider is 1.25 px, drawn as an inset shadow.elevation-0is flat.elevation-1(popover, toast, floating timer) andelevation-2(dialog, withscrim) are the only shadows. Shadows never decorate containers.- Glass only on the top bar (brand-tinted
topbar-bg, 35%) and the floating timer (glass-bg, saturate 1.4), both at a 16 px blur. Popovers and the toast stay opaque so their text holds 4.5:1. - Layers are named
z-*: popover 70, toast and drawer 60, front door and scrim 55, floating timer 50, shell 45, tip 20, local 5, raised 2. Dialogs use the browser's top layer.
Motion
ease-out— cubic-bezier(0,0,0,1) — is the signature curve.duration-fast.16s for color, press and exits;duration-in.26s on the way in;duration-out.4s on the way back.- Whole-card targets lift 9 px. Buttons rise 1 px and press to .97. Icon buttons go to 1.08 on hover and .86 on press. Rows only tint.
- Entrances rise or pop in over .26s; every entrance has an exit, playing the same values back over .16s on
ease-in. - Pages rise in block by block: 10 px over .36s, staggered 1/30 s, capped at 12 blocks. The Home intro and the front door use
ease-soft. - Reduced is a token mode: movement stills, fades stay, the card lift is kept, and a page change becomes a crossfade (.12s out, .18s in).
- Animate transforms, opacity and color only. The sidebar collapse (.2s) is the one layout motion.
Focus and states
- Focus is a 2 px
accent-ringoutline at a 2 px offset, at 3:1 for any accent. Inputs add the 3 pxaccent-halo. - Disabled controls use
opacity-disabled(.5). - Hover on a pastel fill uses
on-color-hover; on neutrals,surface-2.
Imagery
None in the chrome. Images are user content, shown on image-backdrop. No illustration, stock, mascots or gradients — the Premium badge (butter into amber at 135°) is the one gradient.
The invoice sheet and the report are paper-white (paper, paper-ink, paper-line…) in both themes, with shadow-paper on screen only.
Iconography
- One inline SVG set of 52 glyphs on a 20 px grid: a 2.5 px margin, a 1.75 stroke (
icon-stroke), round caps and joins,currentColoronly. In code:HeyGoal.ico(name)fromcomponents/bundle.js. Each glyph is also an SVG in the Icons asset group (drawn incurrentColor, which an<img>renders black — inline the SVG to color it). - Sizes: 16 in text and pills (
icon-size-sm,.ico.sm), 20 in menus and controls (icon-size,.ico), 24 in the phone bar (icon-size-lg,.ico.lg). Never in between. - The set: home, check, folder, clock, receipt, note, user, gear, plus, trash, tick, play, stop, pause, hidemenu, download, upload, grip, palette, eyeoff, layout, sun, moon, x, reset, crop, users, link, edit, image, copy, report, left, right, calendar, external, dollar, flag, text, menu, sidebar, folderplus, invoice, signout, signin, calplus, star, lock, send, print, cloud, cloudoff.
- Every icon-only button has a label: it becomes the tooltip and the accessible name.
- No icon font, no PNG icons, no emoji. The Google sign-in button keeps Google's own G.
Logo
- The mark is final (2026-10-11): the HeyGoal wordmark with the check,
brandblue #0080ff and navy #080044. All versions are in the Logo asset group; the Logo versions card shows each on its ground. - Light grounds:
heygoal-wordmark-color-light.svg. Dark grounds:heygoal-wordmark-color-dark.svg. Brand blue or photos:heygoal-wordmark-white.svg. One-color print: navy or black. - The symbol (the check with its foot) stands alone only in square or small spaces: app icon, favicon, avatar, loading state. The app icon is
heygoal-app-icon-filled.svg; outline is for white app stores. brand-inkis the letters' color: navy on light,neutral-50on dark. The check is alwaysbrand, never the accent.- Clear space is x on every side, x = the height of the check's foot (about 24% of the logo's height). Minimum 20 px tall for the wordmark, 16 px for the symbol.
- Slots: 24 px tall on the desktop bar (
logo-height-bar), 20 px on the phone bar, 52 px on the front door, 16 px for the favicon. - The phone bar names no page: the logo, then the timer chip, the avatar and the menu button. The page heading names the page.
- Never stretch, recolor, outline or add effects to the mark, and never put the full-color logo on brand blue.
design-system\HeyGoal design system · works offline, open any page in a browser.