9.8 KiB
RealBrain Design System — instructions for coding agents
Copy this file into a RealBrain repository as AGENTS.md (or append it to CLAUDE.md). It tells an agent how to apply the design system without being reminded each time. Adjust the one path in "Source of truth" to wherever the repository vendors tokens.css.
Source of truth
- In this repository:
src/tokens.css— a vendored copy of https://realbrain.cc/design-system/tokens.css. Never edit it by hand; refresh it withcurl -o src/tokens.css https://realbrain.cc/design-system/tokens.css. - Full guide: https://realbrain.cc/design-system/design-system.md
- Short reference for agents: https://realbrain.cc/design-system/llms.txt
- Tokens as JSON (DTCG): https://realbrain.cc/design-system/tokens.json
Read the guide's §2 (non-negotiables) and §6 (components) before writing or editing any CSS, component, or UI copy.
Rules
- Tokens only. Every colour, size, radius, shadow, duration, and easing in component code is a
var(--token)fromtokens.css. No raw hex, no raw px, norgba(). - One accent per screen. Exactly one
.btn-primary(or one accent-coloured action). Everything else is.btn-secondary,.btn-ghost, or neutral text. - Weight ≤ 600. Never
font-weight: 700orbold. The font import does not even load 700. - Flat. No
linear-gradient,radial-gradient,backdrop-filter,text-shadow, glow, or decorativebox-shadow.--shadow-*is only for surfaces that are actually elevated (menus, modals, toasts). - Never white on accent. Text and icons on
--accentuse--accent-fg. - Semantic colour is never the only signal. Use
.status.ok|warn|err|info(dot plus text) or an icon plus text. - Copy: sentence case everywhere. Buttons are verbs ("Sign in", "Create project"). "Sign in", never "Log in" or "Login". Errors say what happened and what to do next.
- One density per product.
.density-comfortable(default, 44px controls) or.density-compact(32px) on a container. Never both. - Use the existing component classes (
.btn,.field,.input,.select,.checkbox,.radio,.toggle,.card,dialog.modal,.toast,.tabs,.table,.status,.scaffold,.empty,.skeleton). Do not re-style them locally. Do not build a div-based fake of a native control. - Motion goes through
--dur-1/2/3and--ease. Nothing else. Reduced motion is handled globally bytokens.css.
When the system doesn't have what you need
Do not invent a value. Build the piece from existing tokens if you can. If you genuinely need a new token or component, ship the work with a clearly marked proposal in your final message:
⚑ NEW TOKEN --{category}-{name}: {value}
why nothing existing fits: …
Do the same for drift you notice in existing code (⚑ DRIFT file:line #3b82f6 → --accent) rather than silently patching it.
Self-check before you finish
Run these from the repository root (adjust src and the excluded path). Every command should print nothing:
# raw colours or px outside the token file
grep -rnE --include=*.css --include=*.vue --include=*.jsx --include=*.tsx --include=*.svelte \
--exclude=tokens.css '#[0-9a-fA-F]{3,8}\b|rgba?\(|\b[0-9]+px\b' src
# forbidden weight and effects
grep -rnE --include=*.css --include=*.vue --include=*.jsx --include=*.tsx --include=*.svelte \
--exclude=tokens.css 'font-weight:\s*(700|800|900|bold)|linear-gradient|radial-gradient|backdrop-filter|text-shadow' src
# copy rules
grep -rniE --exclude-dir=node_modules 'log ?in|Sign In\b|Log In\b' src
Then check by eye: one .btn-primary per screen, focus rings visible when tabbing, and every status or badge has text next to its colour.
Quick reference
--bg #080808 light: #F7F7F9
--surface #121216 light: #FFFFFF
--elevated #1A1A20 light: #FFFFFF
--text-1 #F4F4F6 light: #16161C
--text-2 #A9A9B4 light: #4C4C58
--text-3 #83838F light: #6E6E7A
--accent #8FA8FF light: #3450C8
--accent-fg #080808 light: #FFFFFF
--accent-hover #9EB5FF light: #4C6BD2
--accent-pressed #6173B1 light: #21358A
--success #3ECF8E light: #177A4E
--warning #E8B23D light: #8A5A00
--error #F26D6D light: #C2373C
--info #62B0F5 light: #1D62A8
--border #26262E light: #E3E3E9
--border-strong #3A3A46 light: #C6C6D0
--font-ui 'IBM Plex Sans', system-ui, sans-serif
--font-mono 'IBM Plex Mono', ui-monospace, monospace
type steps display:60/64 8:40/48 7:30/38 6:24/32 5:20/28 4:17/26 3:15/24 2:13/20 1:12/16
weights 400 · 500 · 600 (never 700)
space 4px 8px 12px 16px 24px 32px 48px 64px 96px
radius sm 6px · md 10px · lg 16px · full 999px
motion 120ms · 200ms · 360ms · ease cubic-bezier(.22,.61,.36,1)
layout marketing 1200px · app 1440px · control-h 44px (compact 32px)
Light theme: document.documentElement.setAttribute('data-theme', 'light'). Dark: remove the attribute.
Untrace specifics
Batch workflows (1.6.0, 2026-09-10)
BatchWorkspace.svelte owns the sequential queue. processing.js creates a terminable worker per scan/encode task. image-worker.js uses the shared scanner and cleaner with OffscreenCanvas. Keep incomplete scans visibly uncertain. desktop/preload.cjs exposes only folder selection and saving; desktop/output.cjs validates the sender and creates unique files exclusively in the user-selected directory. Never expose generic IPC or unrestricted filesystem access. Saved export settings use untrace-export; theme settings keep their existing key.
Themes and branding (1.3.0, 2026-09-10)
The derivative is named Untrace Desktop, as requested by the user. Branding
lives in desktop/brand.json; build metadata in package.json must match it.
Keep upstream Untrace attribution and the MIT license.
The user explicitly requested more themes. src/themes.css is the local palette
source: it overrides existing semantic colour tokens for dark, graphite, paper,
cobalt and ember without editing vendored src/tokens.css. Palette definitions may
contain raw colours; components must continue using tokens. Exclude both palette
files (tokens.css, themes.css) from the raw-colour self-check. No new token names
are introduced. The theme catalog and shared pre-paint bootstrap are in
src/lib/theme-catalog.js. Appearance is a native dialog with radio controls.
Desktop workspace (1.2.0, 2026-09-10)
The active application is src/lib/Workspace.svelte, mounted by src/App.svelte.
It uses a full-window preview and inspector, not the historical landing page or
stepper. Older website components remain as upstream reference and are not imported.
The active stylesheet is src/app.css; it composes the existing tokens and keeps
comfortable density. There is one primary action: choose an image, clean it, or
save its result. Help is a native dialog. Keep the image processing limitations
accurate when editing copy. npm test verifies the workspace in Electron and
npm run portable creates the Windows release. Earlier specifics below describe
the upstream baseline.
Applied to this repository on 2026-09-05, design system v2.0.0.
src/tokens.cssis the vendored copy.src/app.cssimports it and adds only app-level composition (layout, dropzone, stepper, disclosure, tiles, the mobile action bar). No component fromtokens.cssis restyled locally.- Density is comfortable throughout — this is a consumer surface.
- Dark is the default.
src/lib/theme.jsreads a saved choice first and falls back to the operating system, andindex.htmlapplies the result before first paint so the page never flashes the wrong surface. - One
.btn-primaryper step of the tool: the dropzone step has none, review has "Clean image", download has "Download clean image". - There is no Tailwind and no PostCSS. The design system is plain CSS and the app needs nothing on top of it.
Open token proposals
NEW TOKEN --border-w: 1px
why nothing existing fits: every surface in the system draws a 1px
hairline, but the width itself is only ever written literally inside
tokens.css. Defined locally in src/app.css until the system adopts it.
NEW TOKEN --topbar-h: 56px
why nothing existing fits: no layout token covers a sticky product bar.
Derived locally as calc(var(--space-7) + var(--space-2)).
NEW TOKEN breakpoints — 560px / 768px / 900px
why nothing existing fits: the system documents container maximums
(--max-marketing, --max-app) but no breakpoint scale. Custom properties
cannot be used in a media query, so a literal is unavoidable; this app
pins itself to exactly these three widths.
src/lib/clean.js contains one literal hex, JPEG_MATTE = "#FFFFFF". That is
image data written to a canvas, not interface styling, so it is intentionally
not a token.
Windows distribution (1.7.0, 2026-10-25)
npm run release:windows builds separate x64/x86 installer and portable packages. scripts/build-windows.mjs pins Electron 44.3.0 for x64 and 43.8.3 for x86 because 44 removed ia32 binaries. Electron 43 support ends in January 2027; do not silently remove that support limitation from the docs. Installed settings use %APPDATA%\Untrace Desktop; portable launcher settings remain in the existing adjacent Untrace-data folder. desktop/data-path.cjs centralizes this distinction. Preserve settings on uninstall. Run installer checks sequentially and separately from app tests, because the installer closes other processes with the application executable name.
Both remotes default to main. See docs/UPSTREAM-REVIEW.md before importing upstream website changes. Regenerate real-workspace screenshots with npm run screenshots using only the generated sample artwork.