Tokens
Say what it means. The value follows.
An agent asks for an intent. The theme gives the right value for light or dark.
The OpenAct design system
The Promptbook holds the tokens, the rules and the checks for OpenAct apps. It is one file. App developers read it. Their coding agents read it before they build a screen.
v1.0.0 · 15 cues · 60 tokensPaste this into your coding agent
Claude Code · Codex
You build an app for OpenAct. Before you write UI code, read the OpenAct Promptbook at https://openact.ing/design/promptbook.md and AGENTS.md. - Pick colors by intent from the Promptbook tokens. Never write a hex value. - Build screens from the blocking patterns and the @openact/ui components. - Show agent work with the AgentState component and its five states. - Write all text in ASD-STE100 style: short sentences, active voice. - If the app needs an accent, run: npm run design -- seed <app-id> <hue> - Before you finish, run: npm run design -- check, then npm test. - In the pull request, list the cues that need a review by a person.
In a theater, the prompt book is the stage manager's master copy of the show. It holds the script, every cue and every move. The crew works from it. Today, much of the crew that builds software is coding agents. They need the same master copy.
The source is a JSON file and a Markdown file, not a picture. An agent can read every rule. So can a person.
Pick a token by what it means. Use status-done for a done task. Never pick a green because it looks good.
A new app gives one hue. A script makes the light and dark values and tests their contrast.
Agent work has five states with their own tokens. A person can always see what the agent does.
A rule is a cue. Each cue has a script, a test or a review by a person.
Seven parts. Each part lives in the code, and this page draws itself with the same token values.
Tokens
An agent asks for an intent. The theme gives the right value for light or dark.
Components
Every app builds from the same kit in @openact/ui. Icons come from Lucide through one Icon component.
Agent states
Every agent surface uses five states. People learn one set of signs. The agent never goes past the wait state on its own, and agent work never uses the brand colors.
thinkactwaitdonefailThe agent wants to make 2 changes.
Motion
Enter, leave and move. Every animation stops for reduced motion.
Contrast
Every text pair needs 4.5:1 in both themes. The lower of the two themes shows here.
Ship
This check failed while we wrote the Promptbook. Our first wait color was too close to the brand gold. The fix was one line.
Items that move through stages.
A list and the open item.
Long text on a page.
Settings and new items.
The agent beside the work.
Use this method when you start an OpenAct app with a coding agent. The person decides. The agent does the work and runs the checks.
| Step | The person | The agent |
|---|---|---|
| 01Script | Writes the premiseOne sentence about who uses the app and what they do. | Reads the PromptbookPicks the blocking pattern for each screen. |
| 02Cast | Picks one hueOnly if the app needs its own accent. | Runs the seednpm run design -- seed <app-id> <hue>, then pastes the tokens into theme.css. |
| 03Block | Approves the screensA short list, one pattern per screen. | Builds the screensFrom the pattern and the @openact/ui components. |
| 04Cue | Names the risky actionsSays which agent actions need approval. | Writes the states and textAgentState for agent work. ASD-STE100 for every sentence. |
| 05Rehearse | Looks at every screenLight and dark, on a phone and a desktop. | Runs the checksnpm run design -- check and npm test. Fixes every problem. |
| 06Open | Reviews and mergesChecks the cues marked review. | Opens the pull requestLists the cues that need a person. |
Step 02 in practice
Most apps need no accent. When an app needs one, give the script a hue from 0 to 360. It finds a light and a dark value with 4.6:1 or more on the page and on cards. It also picks the text color for buttons in that accent.
$ npm run design -- seed advisory 160 /* In :root */ --app-advisory-accent: #0e8557; /* 4.65:1 on page and card */ --app-advisory-accent-foreground: #ffffff; /* 4.65:1 on the accent */ /* In .dark */ --app-advisory-accent: #23c987; /* 8.34:1 on page and card */ --app-advisory-accent-foreground: #0d0f14; /* 8.92:1 on the accent */ /* In @theme inline */ --color-app-advisory-accent: var(--app-advisory-accent); --color-app-advisory-accent-foreground: var(--app-advisory-accent-foreground);
A script checks some cues with every npm test. A test covers one. A person checks the rest in the pull request.
| Cue | Rule | Check |
|---|---|---|
| C01 | Use theme tokens for every color. Do not write hex, rgb or oklch values or fixed Tailwind palette classes in components. | script |
| C02 | Give every token a light value and a dark value. | script |
| C03 | Text has a contrast of 4.5:1 or more on its surface, in both themes. | script |
| C04 | Status marks, icons and lines that carry meaning have a contrast of 3:1 or more. | script |
| C05 | Pick a token by its intent. Do not pick a token by its color. | review |
| C06 | Use one primary action on a screen. | review |
| C07 | Every signed-in page starts with SiteHeader and puts its content in PageBody. | review |
| C08 | Build from the shadcn/ui components in @openact/ui. Use Lucide icons through Icon. | review |
| C09 | Show agent work with the five agent states and the AgentState component. Never show agent work in the brand colors. | script |
| C10 | An agent change that deletes data or changes people waits for a person. Show Approve and Reject. | test |
| C11 | Use the motion tokens. Stop every animation when the person asks for reduced motion. | review |
| C12 | Write text in ASD-STE100 style: short sentences, active voice, one idea per sentence, American spelling. | review |
| C13 | Do not use em dashes in text. | script |
| C14 | Start the name of an app token with the app id, such as --app-docs-accent. | script |
| C15 | Look at every new screen in light and dark, on a phone and on a desktop, before you open a pull request. | review |
The build reads these values from theme.css. Stage surfaces and identity colors are in promptbook.json.
| Class | Intent | Light | Dark |
|---|---|---|---|
| agentThe five states of agent work. They never use the brand colors. | |||
agent-think | The agent reads and plans. | #5d6675 | #a3adbb |
agent-act | The agent runs a tool. | #2f5bd3 | #8aabff |
agent-wait | The agent needs a person to approve or reject. | #8a35c9 | #cf9cff |
agent-done | The agent finished the step. | #1b7a4b | #56c98f |
agent-fail | The step failed or a person rejected it. | #c0392b | #f37b63 |
| meaningColors that carry meaning. Never use them for decoration. | |||
status-backlog | Status: not planned yet. | #8d99a9 | #7c899d |
status-todo | Status: planned. | #4a78c7 | #6c9ae9 |
status-doing | Status: in progress. | #c47b10 | #e8a138 |
status-review | Status: waiting for review. | #8658c4 | #a886e6 |
status-done | Status: done. | #2c9662 | #4abc82 |
priority-high | Priority: high. | #c0402b | #f37b63 |
priority-med | Priority: medium. | #a8711a | #e1aa4c |
priority-low | Priority: low. | #737373 | #a3a3a3 |
live | Something changes now, such as another viewer on the page. | #2c9662 | #4abc82 |
today | The line for today on a timeline. | #d53f2c | #fe6a54 |
warn | The fill of a warning. | oklch(0.97 0.04 85) | oklch(0.27 0.04 75) |
warn-foreground | The text of a warning. | oklch(0.42 0.09 70) | oklch(0.86 0.1 85) |
warn-border | The edge of a warning. | oklch(0.86 0.09 85) | oklch(0.42 0.07 75) |
| brandThe OpenAct identity: Playbill ink with a stage gold cue. | |||
brand | The ink of the OpenAct mark. | #1c1824 | #ece7f2 |
brand-foreground | Text on the brand ink. | #ffffff | #1c1824 |
brand-gold | The cue light. Use it for brand moments only, never for status. | #8a6420 | #e3b85c |
| actionThings a person can do. | |||
primary | The main action on a screen. Use one per screen. | oklch(0.205 0 0) | oklch(0.922 0 0) |
primary-foreground | Text on the main action. | oklch(0.985 0 0) | oklch(0.205 0 0) |
secondary | Other actions. | oklch(0.97 0 0) | oklch(0.269 0 0) |
secondary-foreground | Text on other actions. | oklch(0.205 0 0) | oklch(0.985 0 0) |
accent | Hover and selected states. | oklch(0.97 0 0) | oklch(0.269 0 0) |
accent-foreground | Text on a hover or selected state. | oklch(0.205 0 0) | oklch(0.985 0 0) |
destructive | An action that deletes or cannot be undone. | oklch(0.577 0.245 27.325) | oklch(0.704 0.191 22.216) |
destructive-foreground | Text on a destructive fill. | #ffffff | #ffffff |
| surfaceThe planes that content sits on. | |||
background | The page. | oklch(1 0 0) | oklch(0.145 0 0) |
foreground | Text on the page. | oklch(0.145 0 0) | oklch(0.985 0 0) |
card | A raised panel, such as a task card or a dialog. | oklch(1 0 0) | oklch(0.205 0 0) |
card-foreground | Text on a card. | oklch(0.145 0 0) | oklch(0.985 0 0) |
popover | A menu or a popover. | oklch(1 0 0) | oklch(0.205 0 0) |
popover-foreground | Text in a menu. | oklch(0.145 0 0) | oklch(0.985 0 0) |
muted | A quiet fill, such as a hover row or a code chip. | oklch(0.97 0 0) | oklch(0.269 0 0) |
muted-foreground | Secondary text: dates, help text, counts. | oklch(0.535 0 0) | oklch(0.708 0 0) |
border | Lines between parts. | oklch(0.922 0 0) | oklch(1 0 0 / 10%) |
input | The edge of a form field. | oklch(0.922 0 0) | oklch(1 0 0 / 15%) |
ring | The focus ring. | oklch(0.708 0 0) | oklch(0.556 0 0) |
scrim | The shade behind a dialog or a sheet. | oklch(0 0 0 / 50%) | oklch(0 0 0 / 65%) |
Start from the repository. Give your agent the prompt at the top of this page. Keep the person in charge of every cue marked review.
git clone github.com/marketgrowth/openactnpm run design -- check and npm test