Design — project settings › Public address: the subdomain claim, the custom-domain flow with its DNS instructions and every certificate state, the primary control and the tier upsell
Draw the settings surface a customer configures their public address from — a NEW pane under Project settings, in the access group beside Members & access. Nothing draws it today: design/projects/access-members.mock.html draws the access level and the share link (Panel 6 of design/public-projects/), and neither depicts a subdomain, a domain, a DNS instruction or a certificate state. This asset is that room.
Three files, the repository convention: design/projects/public-address.mock.html (the source of truth — standalone, the shipped --el-* tokens and components/ui/* primitives restated), design/projects/public-address.png (chromium export, deviceScaleFactor: 2), and a new section in design/projects/design-notes.md with the surface table and the panel list. Design to the shipped primitives — Card, Input (+ helperText for the live preview), Button, Pill, Modal, Tooltip, EmptyState, ErrorState — and to the settings-pane grammar access-members.mock.html established; invent no primitive.
What the asset draws (inspect every panel)
| panel | what it shows |
|---|---|
| 0 | The access path — the rail entry Public address in the access group between Members & access and Roles (lib/settings/projectSettingsNav.ts), and the door from the make-public flow: the share-link row in Panel 6 of design/public-projects/ gains a Set up your own address → link here. Draw both entrances. |
| 1 | No subdomain claimed — the claim Input with the live preview <label>.<base> in helperText (the create-project identifier grammar), the grammar hint, and a reserved / taken inline error. |
| 2 | Claimed — the address row (acme.<base>/<identifier>, copy button, open ↗), the Rename affordance with its warning copy "the old address keeps redirecting and cannot be claimed by anyone else · N renames left", and the rename confirm. |
| 3 | Custom domains — empty, with Add a domain; 3b the tier gate: the same panel on a free org — Add a domain disabled, the upgrade prompt in the EntitlementExceededError grammar 8.1.7/8.1.8 use (design/billing/ — compose, do not redraw). |
| 4 | Add a domain — hostname input → the DNS instruction block: the CNAME (or A/AAAA for an apex, chosen by the shape typed) and the _motir-verify TXT, each with name / value / copy; Verify and I'll do this later. |
| 5 | The state set, one row per value — unverified, verifying, pending_certificate, issued, failed (with failureReason), expired, revoked — every enum value the store carries, each with its Pill tone, its one-line meaning, and the action a customer can take (re-check, show DNS again, remove). No value may be undrawn. |
| 6 | Primary — the Primary address radio across motir.co/p/<identifier>, the subdomain path, and each issued custom domain (non-issued rows disabled with a tooltip), plus the consequence line "every other address redirects here". |
| 7 | Remove a domain — the confirm (archive-confirm grammar), stating that the certificate is removed and the address stops answering. |
| 8 | Non-admin — read-only: addresses visible, no controls (the canManage gate the members pane uses). |
| 9 | Narrow (390 × 844) and dark. |
Composes, does not redraw: the settings shell and rail (design/projects/settings-area.mock.html), the upgrade prompt (design/billing/), the share-link row (design/public-projects/ Panel 6). The behaviour it depicts is specified by the subdomain service, the lifecycle and the status job — read their bodies and the ADR Q4/Q6/Q7 before drawing, and cite which card each control came from in the notes. (These are relates_to links in spirit; a proposal cannot carry that edge, so the approver wires them after approve.)
Sweep the asset before it leaves your hands (gate 8's design-allocation limb): for every card this asset names, state whether it GIVES or TAKES an element, a structure or a premise, and re-estimate the settings pane card on the record if what you drew exceeds what it is sized for.
Acceptance criteria
- The three files exist under
design/projects/and the PNG is a fresh chromium export of the mock;design-notes.mdcarries the surface table, the panel list, and the access-path table naming both entrances. - Panel 5 draws all seven customer-domain states plus the two subdomain states (
active,alias) — one row per enum value — each with a meaning and an action; agrep -cof the state names over the mock matches the enum's cardinality. - Panels 0 and 3b compose the shipped rail, settings shell and upgrade-prompt assets by citation, and the notes state they are not redrawn.
- Every control's behaviour is attributed in the notes to the card that specifies it; a behaviour with no specifying card is flagged in the notes' Planning flags section, not invented.
- The design-guards lane (
vitest.design.config.mts— ink contrast, token parity) is green on the new mock in both themes. - The allocation sweep is written into the notes (GIVES / TAKES per named card) and any re-estimate it implies is recorded on that card.
Context refs
motir-core/design/projects/design-notes.md·access-members.mock.html— the settings-pane grammar (radio cards, member rows, confirm modals) this composesmotir-core/design/public-projects/design-notes.md— Panel 6 (share link), the build-in-public reframe (6.17), the state rulesmotir-core/design/projects/settings-area.mock.html— the shell and rail;lib/settings/projectSettingsNav.ts— theaccessgroup and its ordering commentsmotir-core/design/billing/— the upgrade-prompt grammar (EntitlementExceededError, 8.1.7 / 8.1.8)motir-core/app/(authed)/settings/project/members/_components/ProjectMembersSettings.tsx— the shipped pane the new one sits beside, and itscanManagegate- the decision — Q4 (DNS + TXT), Q6 (primary), Q7 (rename, reserved), Q8 (tier gate)
- Notion
connect-a-custom-domain-with-notion-sites, Cannysetting-up-your-custom-domain, Statuspageset-a-custom-domain-and-ssl— the mirrors' own settings flows, for the DNS-instruction and verify grammar