Quoin design

Screens

Every screen Quoin has designed so far, indexed by page, with its Paper artboard id.

Every screen lives in one Paper file, the Quoin Paper file, 01M2Q303RK19BADQ6XBRKCD8PK. The file has two pages:

  • "Quoin · standalone" (marketing and sign-in)
  • "Quoin · 1–8". This page holds these groups:
    • Setup
    • Flags
    • Experiments and metrics
    • Analysis and decisions
    • Settings
    • Components on Base UI
    • Motion

Artboard names are the canonical screen ids of Quoin. When a spec or a ticket names a screen, it names one of the artboards below.

Design stage

This index lists what the team has designed so far. People keep it current by hand. It is not a live sync with Paper. Open the file directly for anything that this page does not list yet. Also open the file if a screen may have moved since the last update of this page.

Quoin · standalone (marketing and sign-in)

ArtboardScreen
5NK-0Q0 · Brand/tokens board
4P1-0Q1 · Home
JV5-0Q1 · Shell — error (state). The root ErrorBoundary shows a generic sentence and what to do. It shows a code <snake_case> line only when the error carries a quoinCode (07d qn00c-r3-1; styled in apps/web/app/app.css per qn00c-sync-2). There is no sidebar, because the boundary sits above the shell
4V2-0Q2 · Experiment report — concluded (trial-reminders)
52T-0Q3 · Flags list
5AG-0Q4 · Flag detail, with resume confirm
5HB-0Q5 · Connect your app
5JE-0Q6 · Mobile home
5JF-0Q7 · Mobile report
4P2-0Desktop sidebar node (Home active) — duplicated for every other sidebar state
4JV-0Mobile status bar

Quoin · 1–8 (product surfaces)

The full flow is designed across artboards. Each artboard name starts with its screen id. The flow covers setup, flags and rules, experiments and metrics, analysis and decisions, and settings. The screen ids are:

  • S1/S2 for setup
  • F-series for flags
  • X-series for experiments
  • T-series for settings
  • R-series for rollout reads

This table lists a few key artboards that other pages on this site reference:

ArtboardScreen
BFF-0A1 · Sign in (desktop). It has an email field, "Email me a code", GitHub and Google (QN-01)
CIY-0A1m · Sign in (mobile)
GCK-0A1 · Sign in — rate limited (state). The notice is plain caution text under the disabled "Try again in 0:52" button. The notice is not a Banner
LP0-0A1 · Sign in — invited (state). A1i CAT-0 supersedes it. The canvas renames it to say so, and it is not deleted (07d qn11a-plan-3). Its older copy ("You've been invited to Quoin — sign in with dev@tessellate.dev to join.") names Quoin where the flow means the workspace. Nothing reads it now
CAT-0A1i · Accept invite — the canonical accept-invite screen (07d qn01-plan-12, qn11a-plan-3). It has the inviter banner "Sam Reyes invited you to join Tessellate as editor.", "Join Tessellate", the invited email pre-filled and read-only, "Email me a code", GitHub and Google. QN-11a-ii builds it at /invite/:token
PAV-0A1im · Accept invite (mobile) — it has the layout of CIY-0, with the banner above the heading and the read-only invited email
P67-0A1i · Accept invite — refused: link not valid (state). The heading is "Join Quoin", because the workspace is unknown by design. The sentence is "This invite link isn't valid. Ask the person who invited you to send a new one." There is no banner and no form. The terms line stays (07d qn11a-plan-3)
P75-0A1i · Accept invite — refused: expired (state). The sentence is "This invite to Tessellate has expired. Ask an owner or admin there to send a new one."
P83-0A1i · Accept invite — refused: wrong account (state). The banner stays, because the token is valid. Then the sentence is "You're signed in as mia@tessellate.io, but this invite is for dev@tessellate.dev. Sign out and sign in with that address." The screen also has a secondary "Sign out" button
BT8-0A2 · Check your email — the six-slot OTP Field (component 46)
GDW-0A2 · Check your email — wrong code (state). Filled slots take the 1.5px --color-negative border. The sentence about attempts left is under the button
BY6-0A2 · Check your email — code expired (state). The slots are empty. An active "Resend code" link replaces the countdown
6FG-0S1 · Create workspace — name, URL, and the three environments as read-only always-created rows. development is no longer an optional checkbox (07d qn01-plan-1). The team-size select is gone (07d qn01-plan-2). There is no mobile artboard, confirmed on approval
710-0S2 · Connect your app. It has the two install chips, the defineFlags snippet with its description line (07d qn02a-plan-2), the read line, and the development SDK key in its shown-once box
M9O-0S2 · key already shown (state). It shows after a reload or a later visit. The stored prefix qn_dev_a1b2c3d4… is muted and has no copy control. The sentence is "This key was shown once and can't be shown again. If you didn't copy it, generate a new one." An admin and an owner also see a secondary "Generate a new key" (07d qn02a-plan-4)
MC7-0S2 · key already shown — editor/viewer (state). The box is the same, with no button. The helper ends with "…ask an admin to generate a new one."
B74-0S2m · Connect app (mobile) — it is a different screen, not a squeezed S2. It has the two chips, a real QR and the real address of the route, quoin.app/connect (07d qn02a-plan-9)
R0M-0C1 · Authorize the CLI (desktop) — /cli/authorize, the browser half of quoin login (07d qn03a-plan-3, drawn qn03a-design-1). It has the two-panel shape of A1. The form panel carries the eyebrow "Command line", "Sign in the CLI", the body sentence, the Workspace Select and the accent "Create CLI key" button over "Signed in as mia@tessellate.io". The Select is drawn closed on Tessellate. The route omits the Select when the person belongs to one workspace. The right panel is the terminal that waits. It shows $ quoin login --url https://quoin.app, the own line of the CLI "Opening …/cli/authorize in your browser. Paste the key it shows here." and a Key: ▌ prompt. A caption says that the page sends nothing for the person. There is no sidebar. The page sits outside the app shell, like A1 and S1
R1H-0C1 · key shown (state) — the shown-once box of S2 replaces the Select and the button. The box has "Paste this into your terminal", the qn_op_… key in mono with its copy control, and "Shown once. If you lose it, revoke it under Settings → API keys and create another." The box has no separate "Shown once" caption in its corner, because the first words of the helper say that. The terminal on the right still waits
R1G-0C1m · Authorize the CLI (mobile) — it has the status bar and top bar of S2m. Then it has the same form at full width with 24px gutters. There is no terminal panel, because a phone rarely has the terminal
R3C-0C1m · key shown (state) — the shown-once box at full width replaces the Select and the button
—The "CLI signed in as mia@tessellate.io" text of step 1 of /connect on 710-0/M9O-0 is the end state (07d qn03a-plan-6(6)). Until the own unrevoked operator key of the caller has a lastUsedAt, the route reads Signed in as {email}. It is not drawn as a separate state, because one string differs
7E2-0S3 · Where outcomes come from (desktop) — /connect/outcomes, the events path of QN-05a (07d qn05a-plan-12). It has a RadioGroup of two cards. "Events you send" is checked, with the track() snippet, the edge chip lettered POST {origin}/api/events and the privacy-policy sentence. The in.quoin.app/t/<slug> host that the screen first drew never existed. "Your database" is disabled, with its title and description intact and the caption "Not available yet." QN-05b enables it. The footer has "Continue" and "Either can be added or changed later, per metric."
RSL-0S3 · Your database selected (state, QN-05b) — /connect/outcomes, the onboarding frame (stepper, "Step 3 of 4"). The database card is checked. "Database kind" shows Postgres as text. The verified connection string is read-only, with its password masked. There is no reveal button, because a verified field renders none (07d qn05b-ii-build-1). "Test connection" shows "Verified read-only access in 84ms". The card sentence is "…keeps only the totals." The callout is "Quoin runs your SQL inside a read-only transaction, plus catalog checks that read no rows. It never writes through this connection." QN-05b-ii redrew the screen
84L-0S3 · Your database — connection error (state, QN-05b) — could not reach, drawn to the build (QN-05b-ii). The card keeps its chosen accent ring. The field keeps its normal border, with the masked string and the "Show connection string" reveal button beside it. The helper is under the field. A caution Banner follows (caution fill, title and reason in the foreground colour, no glyph) with "Connection refused" / "Nothing answered on port 5432…", "Test again" and "Switch to events you send →". Then the callout follows. The panel has no negative colour (07d qn05b-plan-14)
10H7-0S3 · Your database — from Settings (state, QN-05b-ii) — /connect/outcomes?from=settings. A person reaches it from the empty state of T5. It has no stepper and no "Step 3 of 4". The database card is chosen, with a pasted string masked and the reveal button beside it. "Test connection" has not run yet. The one footer link is "Back to outcome source", to /settings/outcome-source (07d qn05b-review-1(10))
S99-0S3m · Where outcomes come from (mobile) — it has the status bar and top bar of S2m, and the same header. The two cards are stacked in desktop order (database disabled first, events checked). Then it has the code block at 12px mono, the edge chip and privacy note, and a full-width "Continue"
8I2-0S4 · Invite your team — /invite-team, onboarding step 4 of 4 (07d qn11a-plan-5). The step rail has step 4 as the current step. The heading sentence is "Get a second person in before you're the only one who can turn anything off." The email + role rows have "+ Add another" (up to 10 rows; the canvas draws three). The four-role picker is drawn open, with Owner shown disabled. Its reason line "Promote someone to owner from Members & roles." replaces a description (docs/plans/qn-11a.md Amendment 6: an invite never carries the owner role, 07d qn11a-plan-2). The Invite dialog of T3 has the same picker. Then the screen has "Send invites" and "I'll do this later". QN-11a-ii builds it
919-0S5 · First flag seen — it has the confirmed banner, the meta line that ends with the key of the confirmed environment, development (07d qn02a-plan-6), and the force-on card with its disabled button
879-0F4 · Flag detail — permanent right-rail save pattern (diff, required note, "Save as revision r-NNNN")
5DJ-0Confirm · resume — the team read --shadow-popup from this dialog. It matched on 25 Sep 2026. It is a hand-kept constant and is not synced from Paper (see Components → Shadow)
GFD-0F4b · Stale-write conflict state
A17-0F4b · Rules-frozen state (experiment running)
B75-0F5 · Archive flag
I5U-0F5 · Archive flag — refused, experiment running (state)
AZJ-0Guardrails list, with the "+ Add guardrail" row
E63-0K1 · Metrics list (desktop) — /metrics on the Table component. The columns are Metric / Type / Source / Window / Better / Status / Used by. The drawn vocabulary is proportion · mean, capped p99 · events · your database · 14d · higher · ✓ Tested (07d qn05a-plan-6). Every "Used by" cell is "—" until QN-06 owns an experiments table (metricInUseBy returns null in this slice)
S9A-0K1m · Metrics list (mobile) — one card for each row (07d qn05a-plan-12). A card has the key in mono with "✓ Tested" at the end. Then it has "proportion · your database · 14d · higher", and then "Used by —". The environment is read-only context under the subhead. A phone has no switcher
EVH-0K2a · Metric editor · converted.14d SQL (desktop) — /metrics/:key on the SQL path. Source "Your database" is chosen ("…keeps only the totals."). It has the "SQL · read-only connection" template field and its helper, the positive test Banner "Test run over the last 100 finished-window units, 3–18 Sep: 11.9% converted." and "Save & test". This is the edit screen as built (redrawn by the fix round of QN-05b-ii, 07d qn05b-ii-qa-1). The Key Input, the Kind ToggleGroup (its helper "A yes/no per unit — compared as a proportion, like a conversion rate.") and the Events card are disabled. "Verified read-only access 3 hours ago." is under the SQL helper. The ghost "Delete metric" is at the left of the footer
F8B-0K2a · Metric editor · SQL validation error (state) — the screen refuses the update template as Field.Error under the SQL field (negative line under the field, no fill, no glyph; QN-05b-ii). "Save & test" is disabled. A refusal has no test Banner beside it (07d qn05b-ii-build-2). The edit chrome is the same as EVH-0. Key, Kind and Events are disabled. The last-verified line is under the error. The ghost "Delete metric" is present (07d qn05b-ii-qa-1)
F30-0K2b · Metric editor · items_saved.14d event (desktop) — /metrics/:key, the edit screen (07d qn05a-plan-6/-10). The Key Input is disabled. Kind is the ink-filled ToggleGroup. Source is two radio cards (database disabled). The screen also has the Window NumberField, the Better Select, the Event Input with its seen caption, Aggregation, "Cap outliers at" p99 and the winsorise helper. The footer has the ghost "Delete metric" at the left and "Save & test" at the right
RZG-0K2 · New metric · event never seen (state) — /metrics/new. It has no CLI chip and no Delete. The title is "New metric". The metric is a binomial metric upgraded.14d. The system has not received its Event upgraded. The caption is the sentence of 02-engineering.md §1 verbatim, in caution text, with the "declare anyway" Checkbox under it. It is never a second confirm. Aggregation reads "any occurrence in window". The cap field is hidden for binomial
S3T-0K2b · Frozen · used by a running experiment (state) — a caution Banner above the form carries the sentence of §1 ("Used by 1 running experiment (instant-search-results). Editing it would silently invalidate…"). Every control and both footer buttons are disabled. The state comes from metricInUseBy of the loader
RV3-0K2b · Delete metric AlertDialog (state) — it has the one-click shape of OBX-0: "Delete items_saved.14d?" (the leading "!" on the canvas is a drawing convention that no AlertDialog renders: 07d qn11b-signoff-2, TBD: to remove) / "Nothing that ran against it changes. Nothing new can pick it." / Cancel · Delete metric. There is no typed key, because a metric is not a production kill switch. The confirm is disabled while the metric is in use (07d qn05a-plan-6)
S9B-0K2bm · Metric editor (mobile) — it has the status bar of X3m and its top bar with a back chevron and the crumb "Metrics / items_saved.14d". Every field is at full width. Window and Better are side by side. "Save & test" is full width, with the ghost "Delete metric" centred under it
DZO-0X3m · Mobile report, collapsed Details block
GZA-0X3e · Experiment report — too early (sample key held as TBD: per docs/06-canonical-numbers.md)
CB9-0R1 · Rollout monitor — onboarding.checklist_v2 at 45%
HRO-0R1 · Rollout monitor — empty (state). It reuses the chrome of CB9-0
HY5-0R1 · Rollout monitor — loading (state). It reuses the chrome of CB9-0
109X-0R1 · Rollout monitor — next step while a guard has paused it (state). It has no decision cards. It has one sentence and "Open rollout detail →" to R2 (DEI-0). R2 has the only paused set (07d qn03a-ii-review-1)
DEI-0R2 · Paused by guard — exports.csv_v2 decision view. The AI block cites only the own signal fields of the guard (07f-D2)
BQI-0X5 · Experiment report — concluded, rolled back
7PB-0T1 · Environments — the four rows are production, staging, development and a custom canary. The production row has the protected mark: the 6px muted dot of §26 plus lowercase 12px text, with no fill and no border. The team redrew it from the bordered pill that the canvas first had, to match what shipped (07d qn11b-frontend-4). 8V4-0 and PVU-0 carry the same mark. The columns are Environment / Key prefix / Keys ("2 active", "1 active", "none", "1 active"). The Keys column shows the active-key count (07d qn11b-plan-1). The "Requires a note on every write" Switch that the canvas first drew is never built, because every write takes a note in every environment. Only the custom row carries the "⋯" row-actions trigger. The three seeded rows keep an empty 32px slot (07d qn11b-plan-2). The prefixes are what wordFor() mints: qn_live_ / qn_stg_ / qn_dev_ / qn_canary_. The settings rail is six rows plus Danger zone. General is struck everywhere on this page (07d qn11b-qa-4)
8V4-0T1 · Add environment dialog — it has "Add an environment", the Name field with its canary placeholder and the shared slug helper, and Cancel · Create environment. The same four-row table is behind it
PVU-0T1 · Delete environment typed confirm — it has the shape of E8T-0 for a custom environment: "Delete canary" (the canvas still draws a small negative "!" before the title that the build never renders: 07d qn11b-signoff-2. To remove it from the artboard is TBD:, because a permission check refused the delete in this pass) / "canary holds 4 flag rows and 1 active API key. Deleting it removes both, along with its flag-change history and any recorded exposures, and cannot be undone. Type "canary" to confirm." (This is the as-built sentence, 07d qn11b-frontend-5 and qn11b-signoff-1(2), on the canvas since the three-team pass. The build adds "(and <r> revoked)" after the key count only when the environment has revoked keys. That second state is not drawn, TBD:. The counts come from environments.usage.) / Environment name field, mono, placeholder canary / Cancel · Delete environment, disabled until the typed value equals the key (07d qn11b-plan-2). Seeded environments never open this dialog, because they have no row menu
96P-0T2 · API keys — it shows the client/server keys of the current environment (Name / Environment / Scope / Prefix / Created by / Last used / "⋯"). The revoked production-legacy row is greyed, with italic "revoked 3 days ago" and no "⋯". Then the Operator keys section lists only the own mia-cli of the viewer (qn_op_…; operator keys mint qn_op_, 07d qn11b-plan-3). The captions use the wording of 07d qn11b-qa-3: "Yours only — tied to your account and deleted with your membership if you leave. Not scoped to an environment." and "Revoking a key is immediate — no note, no confirm beyond a click. Revoked keys stay listed, greyed out, for the audit trail — revoking never deletes a key. Deleting its environment, or leaving the workspace with an operator key, does."
AFS-0T2 · Create key dialog — it has Label, and the read-only Environment (the current one of the sidebar switcher, with "Switch environment in the sidebar to create a key for staging or development."). It has the Scope radio group Client / Server (default) / Operator. The Operator helper reads "CLI and web writes, tied to you — deleted with your membership if you leave. Not scoped to an environment." (07d qn11b-qa-3)
AKU-0T2 · Secret shown once — it has <label> created / production · server, and the plaintext row with "copy". It has the caution text "This is the only time you'll see this key. Store it somewhere safe. Closing this without copying doesn't bring it back — creating a new key is the only recovery." (07d qn11b-signoff-1(3), on the canvas since the three-team pass). The "I've stored it somewhere safe" checkbox gates a disabled Done. There is no corner close by design (07d qn11b-plan-5)
APW-0T2 · Revoke key AlertDialog — "Revoke production-client" (the build has no title glyph: 07d qn11b-signoff-2. The "!" on the canvas is TBD: to remove, as on PVU-0) / "This takes effect immediately — any deploy using this key stops reading flags right away. Revoked keys stay listed for the audit trail; create a new key instead of reusing this one." (07d qn11b-signoff-1(3): no regenerate exists for a workspace key. The canvas has read this since the three-team pass) / Cancel · Revoke. It has one click and no typed field (07f-D11)
E0P-0T7 · Danger zone — it has "Irreversible workspace actions.", and the "Delete this workspace" card and its destructive button. The running-experiments banner that the screen draws waits for QN-06 (07d qn11b-plan-5)
E8T-0T7 · Delete workspace typed confirm — "Delete tessellate" (the build has no title glyph: 07d qn11b-signoff-2. The "!" on the canvas is TBD: to remove, as on PVU-0). The 30-day soft-delete sentence ends with "Type "tessellate" to confirm." It sits over a "Workspace URL" field. The typed value must equal the slug (07d qn11b-sync-2). The sentence and the label said "workspace name" while the value was the slug. "Workspace URL" is the own word of /workspaces/new for it. The sentence now quotes the exact value, as PVU-0 does. Cancel · Delete workspace is disabled until the value matches (07d qn11b-plan-5). This is the reference shape for every typed confirm
BIB-0T3 · Members & roles — five-action permission matrix (07f-D8). The 32px slot at the end of the member table row now holds the "⋯" row-actions IconButton on every row except the row of the signed-in person (no self-removal, 07d qn11a-plan-2/-4). Resend/Revoke on the pending row are inline text actions, not a menu
P05-0T3 · Row actions menu open (state). The "⋯" on the row of Dev Patel is pressed. The Menu (component 15) is below it, with its single destructive item "Remove member…". The trigger sits in --color-surface-2. The item sits in --color-negative-subtle
OBX-0T3 · Remove member AlertDialog — "Remove Dev Patel from Tessellate?" / "They're signed out of this workspace right away, and their CLI keys for it stop working. You can invite them again later." / Cancel · Remove member. It has one click and no typed field (the shape of 07f-D11). The sentence is workspace-scoped on purpose. A member of two workspaces keeps their session for the other workspace (07d qn11a-qa-7). The sentence never claims that they are signed out everywhere
OHZ-0T3 · Revoke invite AlertDialog — "Revoke the invite to jules@tessellate.io?" / "The link stops working right away. You can invite them again later." / Cancel · Revoke invite (07d qn11a-plan-4)
OO1-0T3 · Invite dialog — it has "Invite someone to Tessellate", Work email (focused, empty), Role Select with Editor as default, Cancel · Send invite, and the corner close (07d qn11a-plan-4). Refusals render as Field.Error under the email field. They are not drawn
OU3-0T3 · Members & roles — as editor or viewer (state). Role is plain text (no Select). There is no "⋯" column and no Invite button. The pending row has no Resend/Revoke. These come from canManage of the loader (07d qn11a-plan-4). The signed-in person is a viewer here, so Sam Reyes carries the owner role in this fixture
CBA-0 / CJK-0T4 · Settings — read-only Starter-plan card (the $0 tier is called "Starter" everywhere, 07d chief-5a)
IJ8-0T5 · Outcome source — it shows the current source, the masked host, the verified-read-only status, the replace-credential re-probe with the outline "Show connection string" reveal button beside the field, and the switch to events (07f-D9, 07d qn05b-ii-qa-1)
10JX-0T5 · Outcome source — events default (state, QN-05b-ii) — it has the header chip "events", and the kept connection under the heading "Database connection · kept, not the default". It has the replace card with the reveal button. It also has "Switch back to your database" with "New metrics default to events. Your database connection is kept and still verified hourly." and its secondary Button (07d qn05b-review-1(7))
1061-0T5 · Outcome source — probe refused (state) — the Field.Error of the replace field, "This connection can write. Use a read-only credential. (The role can insert into public.orders.)", is under a negative-bordered field with the reveal button beside it. The old credential stays active (07d qn05b-ii-qa-1)
—T5 · Outcome source — empty ("No database connected", "Connect a database" to 10H7-0) and K2 · New metric with the database not connected. The team built and captured these screens (docs/qa/qn-05b-ii/build-1/t5-empty-*, k2-not-connected-*). They are not drawn (07d qn05b-ii-qa-1)
J36-0T5 · Outcome source — probe failed (state, superseded by probe refused) — it is an older drawing kept for history. It has a negative banner, the old subtitle and .internal hosts. 1061-0 is current (07d qn05b-ii-plan-9)
CZN-0L1 · Audit log (desktop) — it is its own top-level sidebar item under Metrics. It is not a Settings-rail row, because audit.list is read-gated and every role sees it (07d qn11c-plan-3). The screen is workspace-wide. The readout at the header right is the date window alone ("last 30 days"). The toolbar is All actors / All object types / Last 30 days / a "Filter by key" search Input last. Then "Export CSV" is a plain text link for manage-keys-members only. The canvas first drew a production ▾ chip. It was a second environment chooser and is gone (qn11c-plan-3). The key Input is auditFilter.key, the control that the "search Input last" of 07b names. The table columns are Rev / Time / Actor / Object / Change / Note. The first row is expanded into its was/now revision diff. The "was · r-0418" / "now · r-0419" labels are --text-xs (12px), the floor. The guard:error-rate actor is caution text, as the same fixture reads on 5AG-0, 4P1-0 and FD8-0. The Home count of the sidebar is the one negative colour of the screen. QN-11c-ii builds it. The "for any flag, experiment, segment or metric" in the subhead is the end-state sentence. The build scopes it to the writers that exist at that release. No L1m is drawn yet

Components on Base UI, and motion

Two further artboards hold the visual reference of the component spec and the motion study. See Components and Motion for the written spec that each artboard backs.

The conventions to edit the file are in the repo, not here: docs/00-context.md, "Paper technical gotchas".

On this page