Files
Untrace/AGENTS.md
T
SharifandClaude Opus 5 00991c1608 Rebuild on the RealBrain design system and retarget SEO to content credentials
Search Console (Jun 4 – Sep 3) shows the page ranking on the first results
page for "content credentials" queries while converting badly: "ai
credentials remover" at 113 impressions and 0.88% CTR from position 6.7,
"remove content credentials from image online" at 2.15% from position 5.0,
"remove ai content credentials from image" at 0% from position 7.8. The
title led with "EXIF metadata", a phrase that appears in none of the top
queries, so the snippet never matched the intent behind the impressions.

SEO
- Title, description and H1 rebuilt around "remove content credentials from
  an image"; EXIF kept as a secondary term.
- Added a how-to section and a nine-question FAQ answering the question
  queries that had no content behind them, including the LinkedIn AI label
  and the Instagram AI tag.
- Structured data as an @graph: WebSite (alternateName "Untrace AI" for the
  unserved brand query), Organization, WebApplication, HowTo, FAQPage.
- Fixed sitemap.xml, which pointed at /untrace/ — a URL that does not exist.
- Regenerated the Open Graph image to match the new design.

Design
- Vendored the design system at src/tokens.css and composed the app from it.
  The old styling broke most of its rules: gradients, font weights 800 and
  900, raw #2563eb, Inter, and emoji as the only status signal.
- Reworked the tool into a Scan / Review / Download flow that lists what it
  found before changing anything, with the primary action pinned within
  thumb reach on small screens.
- Dark by default with a light theme, applied before first paint so the page
  never flashes the wrong surface.
- Replaced the floating donation widget, which painted an off-token circle
  over the page and covered the mobile action bar, with a footer link.

Structure
- Moved detection into src/lib/metadata.js and removal into src/lib/clean.js;
  the canvas callbacks are now a promise chain.
- Dropped Tailwind and PostCSS. Both were configured twice, and no Tailwind
  utility was used. Stylesheet is 6.2 kB gzipped with the whole system in it.

Fixes
- The stepper never advanced: stepState(index) read `current` from the
  closure, which Svelte 4 cannot track as a template dependency.
- The cleaner's fallback returned the original, uncleaned file while the UI
  reported "All EXIF metadata removed". It now reports the failure instead.

Verified against a JPEG carrying EXIF, GPS, XMP and an APP11 JUMBF C2PA
manifest: the output retains only APP0 and the sRGB ICC profile, with every
provenance marker gone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018pRSdR57Ze9M2meDfYZgYE
2026-09-05 23:03:00 +06:00

6.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

Read the guide's §2 (non-negotiables) and §6 (components) before writing or editing any CSS, component, or UI copy.

Rules

  1. Tokens only. Every colour, size, radius, shadow, duration, and easing in component code is a var(--token) from tokens.css. No raw hex, no raw px, no rgba().
  2. One accent per screen. Exactly one .btn-primary (or one accent-coloured action). Everything else is .btn-secondary, .btn-ghost, or neutral text.
  3. Weight ≤ 600. Never font-weight: 700 or bold. The font import does not even load 700.
  4. Flat. No linear-gradient, radial-gradient, backdrop-filter, text-shadow, glow, or decorative box-shadow. --shadow-* is only for surfaces that are actually elevated (menus, modals, toasts).
  5. Never white on accent. Text and icons on --accent use --accent-fg.
  6. Semantic colour is never the only signal. Use .status.ok|warn|err|info (dot plus text) or an icon plus text.
  7. 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.
  8. One density per product. .density-comfortable (default, 44px controls) or .density-compact (32px) on a container. Never both.
  9. 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.
  10. Motion goes through --dur-1/2/3 and --ease. Nothing else. Reduced motion is handled globally by tokens.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

Applied to this repository on 2026-09-05, design system v2.0.0.

  • src/tokens.css is the vendored copy. src/app.css imports it and adds only app-level composition (layout, dropzone, stepper, disclosure, tiles, the mobile action bar). No component from tokens.css is restyled locally.
  • Density is comfortable throughout — this is a consumer surface.
  • Dark is the default. src/lib/theme.js reads a saved choice first and falls back to the operating system, and index.html applies the result before first paint so the page never flashes the wrong surface.
  • One .btn-primary per 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.