How to Use

Where to start, how the system fits together, and the rules that keep it coherent.

v1.0.0·Updated Jul 9, 2026 · 12:00
Everything is in the name

Optimistic is named for the optimistic update, the pattern where an interface shows the result of an action the instant you take it, then quietly reconciles with the server. The design system is built in that same spirit: fast, confident, and honest when reality disagrees. Read the philosophy for the long version, or start below. Everything lives in one repository: github.com/subinsab/Optimistic.

System requirements

The stack is Next.js and React, so anything that runs a modern Node app runs this. Confirm two things first: node -v and git --version.

RequirementMinimum
Operating systemmacOS 12+, Windows 10+, or a modern Linux
Node.js18.18 or newer (20 LTS recommended)
Package managernpm 9+ (bundled with Node), or pnpm / yarn
Git2.30 or newer
EditorVS Code recommended, or any editor you like
Disk spaceabout 600 MB for dependencies
What you will need

Four free tools. Install Node and Git to run the project; VS Code and Claude are how you will work in it.

Node.js

Runs the dev server, the production build and the component installer. Get the LTS build.

Download Node.js
Git

Clones the repository and tracks the changes you make.

Download Git
VS Code

The recommended editor. Pairs with the ESLint and Claude Code extensions.

Download VS Code
Claude

Build with the AI workflow this system was made for: the desktop app and the Claude Code CLI.

Download Claude
Install and run locally

Four steps to get the documentation site and the full component source running on your machine.

01Clone the repository. Pull the whole design system: tokens, the docs site and the component kit.
terminal
git clone https://github.com/subinsab/Optimistic.git
02Install dependencies. Move into the folder and install. The first run takes a minute.
terminal
cd Optimistic
npm install
03Start the dev server. This also regenerates the token CSS, then serves the docs. Open the printed URL.
terminal
npm run dev
# ready on http://localhost:3000
04Build for production. Regenerates tokens and builds the static docs site.
terminal
npm run build
npm start
Add Optimistic UI to your app

The kit is shadcn-style: instead of a locked npm package, an installer copies the tokens and the components you pick straight into your project, so you own and can reshape every file.

01Open the kit. The installer lives inside the repo you just cloned.
terminal
cd Optimistic/optimistic-ui
02Copy components into your app. Pull the tokens plus the components you want into a folder you own. Run with --list to see them all.
terminal
node install.mjs button notification --dir src/ui
03Import the tokens once. Add this to your global stylesheet. It defines every CSS variable the foundations below use.
css
/* global.css */
@import "./ui/tokens.css";
04Use a component. It is plain React and CSS with no build magic. Edit it freely, it is your code now.
tsx
import { Button } from "./ui/components/button/button";

<Button variant="warm">Ship it</Button>
Using the foundations

Once the tokens are imported, every foundation is a set of CSS variables you consume with var(--token). Nothing is hard-coded, so a change at the token layer flows to every component at once. Here is how to use each one.

Never hard-code a hex. Reach for a role variable (surface, text, border), or a core ramp step for a specific tone. Change a token once and it moves everywhere.

css
.card {
  background: var(--bg-panel);
  color: var(--text-primary);
  border: 1px solid var(--border-default);
}
.card__cta { background: var(--color-brand-500); }

Each text style is one font shorthand plus its tracking. Body 1 (16px) is the default reading size, Header 1 to 5 for titles.

css
.title { font: var(--type-header-1); letter-spacing: var(--type-header-1-tracking); }
.copy  { font: var(--type-body-1);   letter-spacing: var(--type-body-1-tracking); }

Every gap, pad and margin is a step on the 4px scale. Reach for a token, never a raw pixel.

css
.panel { padding: var(--space-300); }        /* 24px */
.row   { display: flex; gap: var(--space-100); } /* 8px  */

A responsive grid: 4 columns on mobile, 8 on tablet, 12 on web, inside a 1320px container. Set how many columns each cell spans per breakpoint with --m (mobile), --t (tablet), --d (desktop).

html
<div class="o-container">
  <div class="o-row">
    <div class="o-col" style="--m:4; --t:8; --d:8">Main</div>
    <div class="o-col" style="--m:4; --t:8; --d:4">Aside</div>
  </div>
</div>

Sharp panels, gently rounded controls, pills for chips. One token per role.

css
.button { border-radius: var(--radius-md); }   /* 6px  */
.card   { border-radius: var(--radius-xl); }   /* 12px */
.chip   { border-radius: var(--radius-full); }

On a dark field, structure comes from a 1px hairline first. Reach for a shadow only when depth carries meaning.

css
.divider { border-top: 1px solid var(--border-default); }
.popover { box-shadow: 0 8px 24px rgba(0, 0, 0, .42); }

Layouts reflow at fixed widths. Design mobile-first, then add columns as space allows.

css
/* mobile-first: 768px tablet, 1024px web */
.grid { grid-template-columns: 1fr; }
@media (min-width: 768px)  { .grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .grid { grid-template-columns: repeat(4, 1fr); } }
How it fits together

The system is atomic. A decision becomes a token, tokens form components, components form products, one unbroken line from Figma to shipped software.

DecisionEvery choice starts life as a Figma Variable, one source of truth, named for its role, not its value.
TokenA generator turns each variable into a CSS custom property: --color-brand-500, --space-300, --type-body-1.
ComponentTokens compose into components, a Button, an Input, a Notification, that read var(--token) and never hard-code a value.
ProductComponents compose into products. Trace any pixel on screen and it ends at a Variable.
The rules that keep it coherent
One warm pixel

The field is monochrome so a single #FF7A00 element can carry all the attention. Never spend it twice in one view.

The hairline is #1E1E1E

Structure comes from one-pixel lines and spacing, not from boxes, shadows or heavier borders.

Honesty over optimism

Render success first, but roll back plainly when the server disagrees. The interface never lies to keep a promise.

Tokens, not values

If you are typing a hex or a pixel into a component, stop. The value belongs in a token so it can move everywhere at once.