FlowOS is for the engineer who owns a workflow in production and wants to know, at two in the morning, exactly what ran and what will run next. Its mechanism is the compiled plan: a drawn graph becomes an ordered set of batches, every step is checkpointed with a dense sequence number, and a run resumes from its last frontier after a crash. The identity is exact and warm: graphite instrument surfaces, one amber that means "running", the frontier tick as the only mark. The distinctive move is that the brand colour is the product's own running state, so a primary button, a live edge and the wordmark all say the same thing: this is executing.
- A blue, purple or teal accent on black. Every workflow tool surveyed (n8n, Temporal, Inngest, Trigger.dev, Windmill, Kestra, Prefect) sits there.
- A glowing generic node graph as the hero, or a customer logo wall. There are no customers to show, and the graph is not the mechanism; the plan is.
- The author's personal brand: no forest green, no gold, no Cormorant, no leaf.
The app is dark by default (operators, long sessions). The landing page and docs are light by default and carry the same tokens in the light block.
:root {
--ground: #0C0C0B; --ground-raised: #111110;
--surface: #151514; --surface-2: #1B1B19; --surface-3: #222220;
--ink-0: #F2F1EC; --ink-1: #DAD9D3; --ink-2: #B9B8B0; --ink-3: #8E8D85;
--line: rgba(242,241,236,.09); --line-strong: rgba(242,241,236,.16);
--accent: #F2B532; --accent-strong: #FFC94A; --accent-ink: #1C1300; --accent-rgb: 242,181,50;
--ok: #62E3A3; --ok-rgb: 98,227,163;
--danger: #FF8A8E; --danger-soft: #FFB3B6; --danger-rgb: 255,138,142;
--wait: #8CCFFF; --wait-rgb: 140,207,255;
--shadow: 0 24px 60px rgba(0,0,0,.36);
}
/* light, for site/ and docs */
:root[data-theme="light"], @media (prefers-color-scheme: light) on the site {
--ground: #F6F5F0; --ground-raised: #FFFFFF;
--surface: #FFFFFF; --surface-2: #EFEEE8; --surface-3: #E6E5DE;
--ink-0: #141412; --ink-1: #2A2A27; --ink-2: #4A4944; --ink-3: #6F6E67;
--line: rgba(20,20,18,.10); --line-strong: rgba(20,20,18,.18);
--accent: #F2B532; --accent-text: #8A5A00; --accent-ink: #1C1300;
--ok: #1B7F4C; --danger: #C2343A; --wait: #1E6FB8;
}Amber is a fill and a stroke. As text it is allowed on the dark ground only;
on paper the words use --accent-text. The four states keep their meaning
everywhere: amber running, green succeeded (only after an observed
node.succeeded), red failed, blue waiting. Selection and hover are ink, so a
selected node is never mistaken for a running one.
Measured with project-design/contrast.py, floors 4.5 text and 3.0 large:
| Pair | Ratio | Pair | Ratio |
|---|---|---|---|
| ink-0 on ground | 17.3 | ink-0 (light) on ground | 16.9 |
| ink-2 on ground | 9.8 | ink-2 (light) on ground | 8.3 |
| ink-3 on surface-3 | 4.6 | ink-3 (light) on ground | 4.7 |
| accent on ground | 10.7 | accent-text on ground (light) | 5.4 |
| accent-ink on accent | 10.0 | ok (light) on ground | 4.6 |
| ok on ground | 12.2 | danger (light) on ground | 5.0 |
| danger on surface | 8.1 | wait (light) on ground | 4.7 |
| wait on ground | 11.6 | accent as text on paper | 1.7, forbidden |
One family with a width axis, plus a mono. Archivo carries the instrument feel: normal width for reading, expanded for the wordmark and eyebrows, so the same face labels the panel and reads the manual.
| Role | Face | Size | Weight | Tracking |
|---|---|---|---|---|
| Wordmark | Archivo, wdth 125 |
14 px app, 20 px site | 700 | -0.01em |
| Display (site hero) | Archivo | clamp(2.5rem, 6vw, 4.25rem), line-height 1.02 | 640 | -0.035em |
| Page title (app) | Archivo | clamp(24px, 2.4vw, 32px), 1.1 | 660 | -0.035em |
| Section (site) | Archivo | clamp(1.5rem, 3vw, 2rem), 1.15 | 620 | -0.025em |
| Body (site) | Archivo | 1.0625rem, 1.6 | 400 | 0 |
| UI text (app) | Archivo | 11 to 12.5 px, 1.45 | 500 to 650 | 0 |
| Eyebrow, label | Archivo, wdth 112, uppercase |
9 to 11 px | 700 | +0.14em |
| Data, ids, events, versions, code | JetBrains Mono | 8.5 to 12 px | 400 to 500 | 0 |
Sources: @fontsource-variable/archivo (wdth.css) and
@fontsource-variable/jetbrains-mono in the app; Google Fonts
Archivo:wdth,wght@62..125,100..900 and JetBrains+Mono on the site.
Never Inter, Manrope, Space Grotesk, or the personal brand's Cormorant.
Radius is a tool language: 6 px inputs and chips, 7 px buttons and node icons, 8 px panels, 10 px cards and nodes, 12 px modals; pills only for status badges. Spacing steps 2 4 6 8 10 12 14 16 18 20 24 32 48 64. Hairlines carry hierarchy; shadow only on things that float (modals, drawers, a selected node). Nested: inner radius equals outer minus the gap.
The frontier tick: a solid line (what has run), a vertical tick (the
checkpoint), then a dotted line (what is planned). It comes from the
executor's ordering mark, the dense schedule_sequence every checkpoint
carries. It is the favicon (frontend/public/favicon.svg, amber field, ink
glyph), the sidebar mark (Icon name="frontier"), and the hero device on the
site as a full execution ruler with a crash and a resume. It never appears as
decoration on a card, a table, or an empty state.
ease-out, 120 to 180 ms, on transform and opacity. The only motion a
person should notice is a running edge (the amber dash flow) and the site's
hero ruler, which plays once. Everything collapses under prefers-reduced-motion.
Operational, exact, plain. Name the mechanism, give the number, say what the system did. On voice: "The run resumed from checkpoint 4 after the worker died." Off voice: "Seamlessly recover from any failure with confidence." No "seamless", "powerful", "any", "AI" (FlowOS runs workflows, not models).
frontend/src/index.cssholds the dark block as its:root; every literal there is one of these tokens, and its@themeblock remaps Tailwind's slate and indigo scales onto them so no utility class can bring a blue back.frontend/public/favicon.svgandfrontend/src/components/icons.tsx(frontier) hold the mark.site/index.htmlcarries both blocks and reads the light one by default.docs/assets/screenshots are captured from the app in its dark theme bydocs/assets/capture.mjs.
Navigation keeps environment, runtime health, location and identity visible.
Registry pages pair live counts with filterable tables. The editor puts
workflow identity, version, dirty state, Run and Save first; the palette is
searchable and grouped by category; the inspector is secondary; both are
overlays on a phone. Nodes expose typed ports, a category tone, config count
and validation state; a node shows only manifest and config facts it has.
Execution detail maps streamed and snapshot evidence onto a read-only graph;
green is an observed node.succeeded, unobserved nodes stay neutral. Every
control keeps a visible focus ring; icon-only buttons carry labels; nothing
scrolls horizontally at 390 px.