Soundcheck design system
The visual language of soundcheck — London's nightlife discovery + diary, on the way to a Goodreads/Letterboxd for clubbing. Every token and component below is drawn from the live product, not invented. One rule above all: dark room, one salmon spotlight.
Brand & voice
soundcheck lives under 6 Minutes — a community-owned London club. The product helps people find the night's best line-ups, preview a DJ's full set in one tap, and keep a diary of who they've seen and want to see.
Personality
Underground, knowledgeable, warm — a clued-in friend, never a corporate listings site. Confident and low-ego. The "6 Minutes" wink (YouTube sets start at 6:00) is the kind of detail that signals care without shouting.
Voice
| Do | Don't |
|---|---|
| "Heart any artist to add to your picks." | "Click here to favourite an item." |
| "No upcoming London date yet." | "No results found (0)." |
| Lowercase, plain, specific. | Title Case Marketing Speak. |
| "Seen live", "Wanna see" | "Watched", "Watchlist" |
Color
A near-black room with a single warm salmon spotlight. Salmon (--accent) is the only hue with meaning — it marks anything interactive, selected, or "yours". Everything else is greyscale so the accent never has to compete.
Accent tints
Salmon at low opacity creates "soft selected" fills and washes — used for hovered calendar cells, picked rows, the wanna-see fill, and CTA panels.
| Token | Used for |
|---|---|
--bg | Page canvas, input fields, ink-on-light contexts |
--surface | Cards, sheets, dock, menus, overlays' content |
--border | 1px hairlines, dividers, idle chip/button outlines |
--fg | Primary text, idle icons |
--muted | Secondary text, metadata, labels, idle controls |
--accent | Interactive, selected, "mine", links, focus |
--ink | Text/icons sitting on a salmon fill |
--muted text on --surface for anything essential — it's for de-emphasis only. Text on salmon is always --ink (#1a0f0e), never white.Typography
Two families. Bricolage Grotesque (800/700) for display + anything branded — tight, characterful, set with negative tracking. Inter for body, metadata, and UI. The signature move: tiny UPPERCASE labels with wide letter-spacing as connective tissue.
London Tonight.
Scale & rules
| Role | Family / weight | Size | Tracking |
|---|---|---|---|
| Hero h1 | Bricolage 800 | clamp(2.8 → 5rem) | -0.04em |
| Sheet / signup title | Bricolage 800 | 1.5–1.8rem | -0.02em |
| Card / tile title | Bricolage 700 | 0.72–1.05rem | -0.015em |
| Big aggregate number | Bricolage 800 | 1.7–2.4rem | -0.02em |
| Section header | Bricolage 800 | 0.82rem | +0.02em |
| Eyebrow / UI label | Inter 700 | 0.54–0.64rem | +0.12 → 0.28em ▲ UPPER |
| Body / lede | Inter 400–500 | 0.92–0.96rem | 0 |
| Metadata | Inter 600 | 0.72rem | 0 |
font-variant-numeric:tabular-nums.Layout & spacing
Centered column, max-width:1180px, side padding that steps down on small screens (40 → 28 → 18px). Full-page in-app views (profile, artist, diary) cap content at 760px for readability.
The event grid
| Viewport | Columns | Gap |
|---|---|---|
| Desktop (default) | 4 | 26 × 22px |
| ≤ 920px | 3 | — |
| ≤ 620px | 2 | — |
| ≤ 380px | 1 | — |
Spacing is informal but consistent — common steps: 4 · 7 · 8 · 12 · 14 · 18 · 22 · 26px. Posters are a fixed 3:4 ratio; artist tiles are 1:1. Reserving these ratios up-front means images never cause layout shift.
Radius & elevation
badge
input
card/tile
sheet/panel
pill
Elevation is quiet. Surfaces sit on the canvas with a 1px --border hairline rather than shadows. Shadows appear only on things that genuinely float — the dock, menus, the picks chip, toasts.
rgba(0,0,0,.6) + backdrop-filter:blur(3px). The player dock is the one element with a 2px salmon top border — it's the "now playing" signature.Motion
| Use | Duration / easing |
|---|---|
| Hover (color, border, bg) | 120ms linear |
| Overlay fade in/out | 200–220ms |
| Sheet / dock slide | 300–320ms cubic-bezier(.4,0,.2,1) |
| Spinner | 0.8s linear loop |
| Ambient marquee | 375s linear loop (barely moving) |
Restraint is the rule. Bottom sheets and the dock slide up with a soft decelerate; overlays cross-fade; controls give a 1px lift on hover. Buttons hovered nudge translateY(-1px). Nothing bounces.
Iconography
Two icon vocabularies: line icons (Lucide-style, 24×24, stroke-width:2, round caps/joins, currentColor) for UI, and brand glyphs (SoundCloud, YouTube) in their own colors for source attribution.
currentColor, so a heart turns salmon simply by being inside an .on control. Brand glyphs keep their platform colors and are never recolored.Generative imagery
When a real poster or artist photo is missing, soundcheck never shows a grey box — it generates a deterministic gradient from the name's hash. Same name → same gradient, every time. Hues stay in the salmon → magenta family so fallbacks feel native, never random.
Event posters (3:4)
genPoster: hue = hash(title) → linear-gradient(ang, hsl(hue 68% 54%), hsl(hue+18 45% 11%)), with a 10% salmon screen tint over everything (real photos included) for tonal unity.
Artist tiles (1:1)
artGrad: hue constrained to 330–400° (pink/salmon). Real artwork (SoundCloud avatar → RA image) layers on top when available, with a bottom-up black scrim so the name stays legible.
Buttons & pills
Almost everything is a pill (border-radius:999px). Three weights: solid salmon (primary), ghost outline (secondary), and bare text. Form/CTA buttons use a softer 10px radius.
| Variant | When |
|---|---|
| Solid salmon + ink text | The one primary action in a view (Follow, Share, Send link) |
| Ghost (border + fg) | Secondary action; hover turns salmon |
| Bare text (salmon) | Tertiary / "More ›" / inline links |
Toggles & switches
Segmented switches and quick-chips share one selected state: salmon fill, ink text. Idle is bordered/muted.
Badges
Tiny uppercase tags in a salmon outline. Pick marks a venue soundcheck rates; Trending marks the most-saved event on a day.
Play pills
A compact 48×23 pill carrying a brand glyph + a tiny state char. Idle is outlined; playing fills (salmon for SoundCloud, foreground-white for YouTube — matching the now-playing source).
Heart · Share · Seen
Round 26–38px icon buttons (sized to context). Idle = muted outline. On = salmon stroke + soft salmon fill. These three carry the entire picks/diary interaction model.
| Control | Meaning |
|---|---|
| Heart (filled) | Wanna see (artist) / Saved (event) |
| Check (filled) | Seen live |
| Share nodes | Share this artist / event |
Event card
The workhorse. 3:4 poster (real or generated) is a button that opens the sheet; below it: optional Pick badge, title, venue · date · time meta, social proof, the line-up with per-artist play + heart, and a card-level heart/share row.
Objekt + Call Super
- Objekt
- Call Super
Artist tiles
1:1 gradient (or real artwork) with the name bottom-left and an optional salmon ✓ for "seen". Used on profile shelves — Wanna-see and Seen-live.
Stats & aggregates
Big salmon Bricolage numbers over tiny uppercase labels — the Letterboxd-y "this many people" texture. Inline panel-stats use bold foreground numbers in a muted sentence.
Hub & profile
The account hub is built from action tiles; public profiles open with a gradient cover + circular initial avatar, a bordered stat strip, and tabs (Shelves / Diary / Network).
Forms & autosuggest
Inputs sit on --bg (darker than the surface around them), 10px radius, salmon border on focus. Labels are tiny uppercase. Star ratings and removable artist chips power the log-a-gig flow.
Surfaces & overlays
Two families. Pages (profile, artist, diary, picks) are full destinations with a "‹ Back" pill and real browser history. Overlays are quick peeks — the event sheet and calendar slide up from the bottom; auth/email modals center. All dim the room with a blurred scrim.
| Surface | Behaviour |
|---|---|
| Event sheet | Bottom sheet (mobile) → centered (≥760px), 18px top radius, slide-up |
| Calendar / picks tray | Bottom sheet with blurred scrim |
| Auth / email gate | Centered modal, 14–18px radius |
| Account menu | Anchored dropdown, heavy shadow |
| Player dock | Fixed bottom bar, salmon top edge, slides up; collapses to a slim strip |
Feedback
Patterns & principles
One spotlight. Salmon is reserved for interactive / selected / "yours". If everything is accented, nothing is.
Never an empty box. Missing poster or photo → a deterministic name-hashed gradient in the salmon family. The product always looks intentional, even with zero imagery.
Pages vs peeks. Destinations are real pages with back-history; quick actions are slide-up sheets. Don't nest a destination inside an overlay.
Mobile-first, thumb-first. Sheets rise from the bottom; the picks chip and dock sit in thumb reach; tap targets ≥26px with touch-action:manipulation.
Fast over fancy. Posters are downscaled + WebP through the image proxy; player SDKs load only on first play; surfaces use 1px borders instead of shadow stacks.
Source-honest. SoundCloud and YouTube keep their brand colors on play pills so people know exactly where a set comes from.
Accessibility
- Focus uses a 2px salmon outline (
outline:2px solid var(--accent)) — never removed without a replacement. - Icon-only controls carry
aria-labeland toggles exposearia-pressed. - Text on salmon is always
--ink(#1a0f0e) for AA contrast; muted text is for non-essential copy only. - Gradient tiles/posters always carry the name as real text on top — the image is decorative, never the only label.
- Body locks scroll behind sheets/overlays (iOS-safe, reference-counted) and restores position on close.
color-scheme:darkis declared so form controls and scrollbars render dark.
Soundcheck Design System v1 — generated from the live product. Tokens & component CSS mirror ra-london-sc/index.html; update both together.