Template
Dockhold
A B2B SaaS starter focused on identity: sign up creates an organization, admins invite members, assign roles, enforce multi-factor authentication and configure single sign-on for their company domain. It shows how to handle tenants, roles and security policies correctly from day one.
Multi-tenant B2B identity starter with organization settings · App · Small tools and apps · full-stack app (auth + DB)
A mock-up of the homepage, drawn from this design’s layout, palette and typefaces. A build follows the full prompt below.
Add app screens
Pick up to 6 screens, such as a dashboard, settings or an empty state. Each is built in this design’s own palette and typefaces, with its states and guardrails.
Start from this templateRead the build prompt
Typefaces
Overpass descends from highway signage, so its clarity reads as serious and trustworthy in a monochrome identity product with no accent colour.
- OverpassHeadings: titles 24px 600 at -0.025em, settings section titles 18px 600
- OverpassBody: body 16px/1.5 400, pitch copy 18px 500, table 15px, labels 14px 500
Patterns
- split-screen auth with dark pitch panel
- single-field email signup card
- organization switcher
- settings sub-nav in left column
- security policy toggle rows
- members table with role badges
- self-service SSO connection wizard
- domain exemption list
States it is designed for
- verification email sent / expired link
- signup with an email domain that already has SSO (redirect to company login)
- only-admin guard (cannot remove last admin)
- pending invitations with send-again and revoke
- MFA enforcement on with members not yet enrolled (warning count)
- SSO test failure with raw error details
- permission denied for members on admin pages
Who it is for
- B2B SaaS founders
- platform engineers
- developers selling to enterprises
Layout
- Auth: two 50% panels; left black panel with wordmark top-left and a short centered pitch; right light panel with 'already joined? log in' top-right and a centered form card; left panel hidden under 768px
- Onboarding: create-organization step (name, slug)
- App top bar: organization switcher left, settings icon and avatar menu right
- Settings: 200px sub-nav (General, Members, SSO, Security policies) + content panel
- Security policies: card with section title, toggle rows and a domain list input
- Members: table with name, email, role select, status; invite form
- SSO: stepper wizard (choose protocol, enter metadata, verify domain, test)
Palette
Serious, trustworthy, monochrome. Black and near-white with no accent colour; security reads through clarity, not decoration.
- auth pitch panel
#000000 - text on pitch panel
#ffffff - auth form side background
#f4f4f5 - primary text (light)
#0a0a0a - secondary text (light)
#666666 - primary button fill
#171717 - input border
#8e8e97 - app background (dark)
#0a0a0b - app card
#18181a - app text
#fafafa - app secondary text
#a8a8a8 - app input / toggle track border
#6e6e73
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | pitch text | 21.00:1 | 4.5:1 |
| Aa | body text | 18.01:1 | 4.5:1 |
| Aa | muted text | 5.22:1 | 4.5:1 |
| Aa | button label | 17.18:1 | 4.5:1 |
| input border | 3.25:1 | 3:1 | |
| Aa | app text | 16.99:1 | 4.5:1 |
| Aa | app muted text | 7.46:1 | 4.5:1 |
| app input border | 3.50:1 | 3:1 | |
| focus ring (dark app) | 18.96:1 | 3:1 |
As vibld’s tokens
The palette on the fifteen colour tokens vibld styles a project with, each text colour on the fill it is read on. Marked tokens are solved from the palette, because no swatch held that role at 4.5:1.
- background
- card
- muted
- primary
- secondary
- accent
- destructive *
Type scale
- Display
- Overpass 600, 24px/1.33, tracking -0.025em
- Body
- Overpass 400, 16px/1.5
Pitch copy Overpass 500 18px/1.55 on black; settings section titles 18px 600; table 15px; labels 14px 500.
Spacing and imagery
Compact enterprise density; auth card max 360px; settings content max 720px; cards 24px padding; radius 8px on inputs, buttons and cards; hairline borders; no shadows.
No imagery; a shield-style logo mark; small lucide icons in the settings nav.
Components
- SplitAuthLayout
- EmailSignupCard
- TermsNotice
- OrgSwitcher
- SettingsNav
- PolicyToggleRow
- DomainListInput
- MembersTable
- RoleSelect
- InviteForm
- SSOWizard (stepper)
- AvatarMenu
- ConfirmDialog
Interactions
- Email signup sends a verification link; card swaps to 'check your inbox'
- Org switcher is a command-style popover with search
- Toggling MFA enforcement opens a confirmation explaining impact
- SSO wizard validates each step before continuing; test sign-in in a popup
- Role changes save immediately with undo toast
Data
Organization{id, name, slug, created_at}Membership{org_id, user_id, role (admin|member), status (active|invited)}Invitation{id, org_id, email, role, token_hash, expires_at}SecurityPolicy{org_id, enforce_mfa (bool), mfa_exempt_domains[]}SsoConnection{id, org_id, protocol (saml|oidc), domain, metadata_url, status (draft|verified|active)}AuditEvent{id, org_id, actor_id, action, target, created_at}
Guardrails
Experience
- Signup asks only for email; organization details come after verification
- Explain the impact of every security toggle in one sentence under it
- Never allow removing or demoting the last admin
- Show which members are affected before enforcing MFA
- SSO wizard shows progress and can be resumed
Accessibility
- Split layout keeps the form first in DOM order on mobile
- Toggles are switches with labels and descriptions linked via aria-describedby
- Org switcher is a combobox with announced results
- Tables have headers and labelled role selects
- Stepper exposes current step with aria-current
- Focus ring 2px dark on light and light on dark
Security
- RLS on every org-scoped table: access only when a membership row links auth.uid() to org_id; admin-only writes check role = admin
- Invitation tokens stored hashed, single-use and expiring
- Enforce MFA server-side (check the session's assurance level) when the org policy requires it
- SSO metadata fetched server-side with URL allowlist and SSRF protection
- Append-only audit log for role, policy and SSO changes
- Rate-limit signup, login and invites
Build prompt
The baseline every prompt in the catalog assumes, then this design’s own ten sections, from goal to guardrails.
The baseline
### How to use these prompts Paste an entry's build prompt into your coding agent as the first message. Each prompt names its own stack, tokens and acceptance criteria; the rules below apply to all of them and can be prepended once per project. ### Engineering baseline - TypeScript strict mode, no `any`, small typed components, feature folders, and one source of truth for design tokens (CSS variables consumed by Tailwind). - Validate every input with a shared zod schema on the client and again on the server or edge function. Never trust client-side checks alone. - Show loading, empty and error states for every async view. Surface errors in plain language with a retry, and log details to the console in development only. - Keep secrets out of the bundle. Only publishable keys (for example a Supabase anon key) belong in client code; service-role keys, API keys and webhooks live in server or edge-function environment variables. ### Data and auth baseline (full-stack entries) - Enable Row Level Security on every table before inserting data. Default-deny, then add owner-scoped policies (`auth.uid() = user_id`) and explicit role checks for admin views. - Store roles in a separate table checked by a security-definer function, never in a user-editable profile field. - Upload files to private storage buckets with size and MIME limits, and serve them through signed URLs. - Rate-limit public endpoints (forms, auth, AI calls) and add a honeypot field or captcha to anonymous forms. - Take payments through a hosted checkout and verify webhooks by signature. Never handle raw card data. ### Accessibility and UX baseline - Target WCAG 2.2 AA: 4.5:1 contrast for normal text and 3:1 for large text, input borders, focus rings and meaningful icons or chart lines. Every palette in this catalog lists its verified pairs; re-check with a contrast tool after any colour change. - Keep body text at 16px or larger with 1.5 line height, nothing below 12px, no light weights under 24px, and uppercase only for short labels. - Give every interactive element a visible focus ring, full keyboard support, semantic landmarks, labelled form fields, and alt text on meaningful images. - Respect `prefers-reduced-motion` for every animation. Give drag-and-drop and carousels keyboard and button alternatives. - Build mobile-first and test at 375px, 768px and 1280px. ### Content guardrails - Use original copy, fictional sample data and placeholder or licensed imagery. Do not reuse another product's name, logo, screenshots or marketing text. - Label demo testimonials and metrics as samples. Collect the minimum personal data the feature needs. ### SaaS screen baseline - Design every screen for its full set of states: first-run empty, loading skeleton, partial data, error with retry, permission-denied, and success feedback. Each entry lists the states its screen needs. - Keep destructive actions (delete, revoke, downgrade, remove member) behind a confirmation that names the object, and prefer undo over a second dialog where the action is reversible. - Enforce authorisation on the server for every action a screen exposes. Hiding a button is not access control; check the role again in the API or RLS policy. - Never show secrets (API keys, tokens) in full after creation. Show them once, then mask them, and offer rotate and revoke. - Keep the app shell (navigation, workspace switcher, account menu) consistent across screens, and preserve filters, sort and scroll position when the user navigates back.
### Goal Build **Dockhold**, a B2B SaaS starter that gets identity right: email signup that creates an organization, member invitations with roles, organization-wide MFA enforcement with domain exemptions, and self-service single sign-on for customer domains. Everything is tenant-scoped and audited. ### Stack Next.js (App Router), React, TypeScript, Tailwind CSS, shadcn/ui (Radix), lucide-react, react-hook-form + zod, TanStack Query. Supabase Auth (email OTP/magic link, MFA with TOTP, SSO/SAML where available) and Postgres for organizations, memberships, policies and audit. ### Pages & layout 1. **/signup**: split screen. Left black panel: wordmark top-left and a centered two-paragraph pitch. Right light panel: "Already joined? Log in" top-right; centered card with title, one-line description, Email field, dark "Get started" button, terms notice with underlined links. Under 768px only the form panel shows. 2. **/login**: same layout; detects SSO domains and redirects. 3. **/onboarding**: create organization (name, slug). 4. **/[org]/settings/general**, **/members**, **/sso**, **/security**: dark app shell with org switcher, settings sub-nav and content panel. Security: "Multi-factor authentication" card with an enforce switch and an exempt-domains input. Members: table + invite form. SSO: four-step wizard. ### Design system - Colors: `--pitch-bg: #000000` (auth pitch panel), `--pitch-fg: #ffffff` (text on pitch panel), `--bg: #f4f4f5` (auth form side background), `--fg: #0a0a0a` (primary text (light)), `--muted: #666666` (secondary text (light)), `--btn: #171717` (primary button fill), `--border: #8e8e97` (input border), `--app-bg: #0a0a0b` (app background (dark)), `--app-surface: #18181a` (app card), `--app-fg: #fafafa` (app text), `--app-muted: #a8a8a8` (app secondary text), `--app-border: #6e6e73` (app input / toggle track border). - Fonts: Overpass 600 titles 24px (-0.025em), 400 body 16px/1.5, pitch copy 18px 500, table 15px. - Spacing: 4px base; auth card max 360px; settings content max 720px; card padding 24px; 16px between rows. - Radius: 8px throughout; switches full. - Shadows: none; hairline borders only. - Motion: 150ms; stepper transitions 200ms; none under reduced motion. ### Components & interactions SplitAuthLayout, EmailSignupCard (swaps to "Check your inbox"), TermsNotice, OrgSwitcher (searchable popover), SettingsNav, PolicyToggleRow (switch + description + confirm dialog), DomainListInput (chips, validates domains), MembersTable, RoleSelect, InviteForm, SSOWizard (protocol, metadata, domain verification via DNS TXT, test sign-in), AvatarMenu, ConfirmDialog, Toast with undo. ### Data & state Tables: `organizations`, `memberships(org_id, user_id, role, status)`, `invitations(org_id, email, role, token_hash, expires_at)`, `security_policies(org_id, enforce_mfa, mfa_exempt_domains text[])`, `sso_connections(org_id, protocol, domain, metadata_url, status)`, `audit_events`. Current org lives in the URL; a SQL helper `is_org_admin(org_id)` backs policies. Seed two invented organizations with five members. ### Accessibility Form comes first in DOM order. Switches are labelled with linked descriptions. Org switcher is a combobox. Stepper marks the current step. Focus ring 2px `#0a0a0a` on light, `#fafafa` on dark. Verified contrast: pitch text: #ffffff on #000000 = 21.0:1; body text: #0a0a0a on #f4f4f5 = 18.01:1; muted text: #666666 on #f4f4f5 = 5.22:1; button label: #fafafa on #171717 = 17.18:1; input border: #8e8e97 on #ffffff = 3.25:1; app text: #fafafa on #18181a = 16.99:1; app muted text: #a8a8a8 on #18181a = 7.46:1; app input border: #6e6e73 on #18181a = 3.5:1; focus ring (dark app): #fafafa on #0a0a0b = 18.96:1. ### Security - RLS on all org tables: select when a `memberships` row joins `auth.uid()` to `org_id`; insert/update/delete on memberships, invitations, policies and SSO only when `is_org_admin(org_id)`. - Prevent removing the last admin with a trigger. - Invitations: hashed, single-use, 7-day expiry. - Enforce MFA on the server by checking the session assurance level against the org policy. - Fetch SSO metadata server-side with SSRF protection; verify domains via DNS TXT. - Audit every role, policy and SSO change; rate-limit auth and invite endpoints. ### Performance & SEO Auth pages static with small client islands; app routes dynamic and noindex. Keep settings pages as server components with client islands for toggles. ### Guardrails - Invent organization names, people and domains. - Never enforce MFA without showing who will be affected. - Acceptance criteria: (1) signup creates an org with the user as admin; (2) members of org A cannot read org B; (3) enforcing MFA forces enrollment on next sign-in; (4) SSO domain users are redirected to their IdP; (5) last admin cannot be removed; (6) every change appears in the audit log.