Template
Chorusdesk
A starter for building document-based collaborative apps: a plain landing page, sign-in, a documents dashboard with organizations and pagination, and several realtime document types (whiteboard, rich text, notes, canvas). Presence, live cursors and a full share menu come ready so teams can focus on their own document type.
Real-time collaborative documents starter · 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
Ancizar Sans is a plain, neutral sans with a wide weight range, so the almost monochrome editor lets the coloured cursors and avatars carry the liveness.
- Ancizar SansHeadings: hero headline 48px 800, section headings 24px 700, card titles 16px 600
- Ancizar SansBody: body 16px/1.5 400, lead 20px, cursor name flags 12px 500
Another design for the same product as Plainwrite, so the gallery lists it there. A collaborative documents app with presence, live cursors and sharing.
Patterns
- minimal landing with left-aligned hero
- 3x2 feature card grid
- document dashboard with sidebar and grid/list toggle
- presence avatar stack
- live cursors with name flags
- share dialog with user, group and public access
- soft yellow radial wash
States it is designed for
- loading skeleton cards
- empty documents with create prompt
- no permission to open document (request access)
- offline / reconnecting banner in editor
- read-only mode for viewers
- public link disabled
- pagination last page
- failed save with retry
Who it is for
- product engineers adding multiplayer
- startups building collaborative tools
- internal-tools teams
Layout
- Header: small mark + product label left, dark 'Sign in' button right; 1px bottom border
- Hero: left-aligned 48px two-line headline, 20px muted paragraph, primary dark button + secondary grey button
- Features: 24px heading, 3x2 grid of bordered cards (title + three-line text); 1 column on mobile
- Footer: copyright line left, 'view source' grey button right
- Dashboard: 240px sidebar (All, Drafts, Organizations, Groups) + main with header (title, new-document menu, grid/list toggle) + document grid with pagination
- Document view: top bar (back, title, presence avatars, Share) above a full-bleed canvas/editor
Palette
Plain, confident, neutral. Almost monochrome UI lets the coloured cursors and avatars carry the sense of liveness.
- page background
#ffffff - primary text
#18181b - secondary text
#71717a - secondary button fill
#f4f4f5 - secondary button label
#52525b - primary button fill
#18181b - input border
#8a8a93 - card / header divider
#ececee - decorative yellow wash
#fffcc5 - presence colour A
#2563eb - presence colour B
#c026d3
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text | 17.72:1 | 4.5:1 |
| Aa | muted lead text | 4.83:1 | 4.5:1 |
| Aa | primary button label | 17.72:1 | 4.5:1 |
| Aa | secondary button label | 7.03:1 | 4.5:1 |
| input border | 3.42:1 | 3:1 | |
| focus ring | 17.72:1 | 3:1 | |
| presence colour A | 5.17:1 | 3:1 | |
| presence colour B | 4.71: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
- Ancizar Sans 800, 48px/1.25, tracking -0.01em
- Body
- Ancizar Sans 400, 16px/1.5; hero lead 20px/1.5
Section headings Ancizar Sans 700 24px; card titles 16px 600; cursor name flags 12px 500.
Spacing and imagery
Generous whitespace; 700px content column on the landing, 1200px app frame; cards 16px padding, radius 12px, 1px hairline borders; buttons radius 6px.
No photos. Document thumbnails are simple previews; presence shown as coloured circular avatars and arrow cursors with name flags; optional soft yellow radial wash on the marketing preview.
Components
- SiteHeader
- HeroActions
- FeatureCard
- DocumentSidebar
- NewDocumentMenu
- DocumentCard
- ViewToggle
- Pagination
- PresenceAvatars
- LiveCursor
- ShareDialog
- PermissionSelect
- EmptyState
Interactions
- Live cursors move smoothly with interpolation and fade after 3s idle
- Avatar stack shows +N overflow with a popover list
- Share dialog: invite by email, set role, toggle public link with copy
- Grid/list toggle persists per user
- Dashboard auto-revalidates when a document is created elsewhere
Data
User{id, name, email, avatar_url, color}Organization{id, name}Group{id, organization_id, name}Document{id, title, type (whiteboard|text|note|canvas), owner_id, organization_id, created_at, updated_at}DocumentAccess{document_id, subject_type (user|group|org|public), subject_id, role (read|write)}
Guardrails
Experience
- Always show who else is here before they type
- Share dialog lists current access before adding new people
- Viewers see a clear read-only badge and disabled toolbar
- Keep the landing to one screen of features; the product is the dashboard
- Document cards show type, title and last edited time
Accessibility
- Presence avatars have names as accessible labels
- Live cursors are aria-hidden; a 'who's here' list is available to screen readers
- Share dialog is fully keyboard operable with labelled role selects
- Cursor colours are paired with name flags, not colour alone
- Focus ring 2px near-black on white
Security
- RLS on documents via document_access: select when a matching row exists for auth.uid(), their groups, their org, or public; write only for role = write
- Realtime room tokens minted server-side per document after an access check
- Only owners can change document_access
- Validate emails and roles with zod; rate-limit invites
- Public links use unguessable ids and can be revoked
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 **Chorusdesk**, a starter for document-based collaborative products. It includes a one-screen landing page, sign-in, a documents dashboard with organizations, groups and pagination, and realtime document types (rich text, notes, a whiteboard) with presence avatars, live cursors and a complete share menu. Teams should be able to add their own document type without rebuilding collaboration plumbing. ### Stack Next.js (App Router), React, TypeScript, Tailwind CSS, shadcn/ui (Radix), lucide-react, TanStack Query (auto-revalidation), react-hook-form + zod, Tiptap for rich text. Supabase Auth (OAuth + email) and Postgres for documents and access. A realtime presence service (or Supabase Realtime) for cursors, presence and document sync. ### Pages & layout 1. **/**: header with mark + product label and a dark Sign in button. Left-aligned hero: two-line 48px headline, 20px muted paragraph, dark "Sign in" and grey "Learn more" buttons. "Features" heading and a 3x2 grid of bordered cards. Footer with copyright and a grey "View source" button. 2. **/signin**: provider buttons. 3. **/dashboard**: sidebar (All documents, Drafts, Organizations, Groups), header with title, "New document" menu (Text, Note, Whiteboard) and grid/list toggle, document cards, pagination. 4. **/doc/[id]**: top bar (back, editable title, presence avatars, Share) and the editor or canvas. Mobile: sidebar becomes a sheet; cards one column; presence shows up to 3 avatars. ### Design system - Colors: `--bg: #ffffff` (page background), `--fg: #18181b` (primary text), `--muted: #71717a` (secondary text), `--subtle-btn: #f4f4f5` (secondary button fill), `--subtle-fg: #52525b` (secondary button label), `--btn: #18181b` (primary button fill), `--border: #8a8a93` (input border), `--hairline: #ececee` (card / header divider), `--wash: #fffcc5` (decorative yellow wash), `--cursor-a: #2563eb` (presence colour A), `--cursor-b: #c026d3` (presence colour B). - Fonts: Ancizar Sans 800 for the hero headline (48px/1.25), 700 section headings 24px, 400 body 16px/1.5, 20px lead; name flags 12px 500. - Spacing: 8px base; cards 16px padding, 24px gap; hero 120px top padding. - Radius: 12px cards, 6px buttons, full avatars. - Shadows: none on landing; popovers `0 8px 24px rgb(0 0 0 / 0.12)`. - Motion: cursor interpolation 60ms; 150ms fades; reduced motion snaps cursors. ### Components & interactions SiteHeader, FeatureCard, DocumentSidebar, NewDocumentMenu, DocumentCard (type icon, title, "edited 3h ago"), ViewToggle, Pagination, PresenceAvatars (+N popover), LiveCursor (arrow + name flag in user colour), ShareDialog (invite by email, role select read/write, groups and organization access, public link toggle with copy), EmptyState, ReconnectingBanner. ### Data & state Tables: `organizations`, `groups`, `group_members`, `documents(id, title, type, owner_id, organization_id, updated_at)`, `document_access(document_id, subject_type, subject_id, role)`. Document content lives in the realtime store keyed by document id; snapshots saved to `document_snapshots` every 30s. Seed two organizations, four users and eight documents with invented names. ### Accessibility Avatars expose names; cursors are decorative with a "People here" list for assistive tech. Share dialog is keyboard operable with labelled selects. Viewers get a read-only badge and `aria-disabled` toolbar. Focus ring 2px `#18181b`. Verified contrast: body text: #18181b on #ffffff = 17.72:1; muted lead text: #71717a on #ffffff = 4.83:1; primary button label: #ffffff on #18181b = 17.72:1; secondary button label: #52525b on #f4f4f5 = 7.03:1; input border: #8a8a93 on #ffffff = 3.42:1; focus ring: #18181b on #ffffff = 17.72:1; presence colour A: #2563eb on #ffffff = 5.17:1; presence colour B: #c026d3 on #ffffff = 4.71:1. ### Security - RLS on `documents`: select when `document_access` grants the user directly, via `group_members`, via organization, or `public`; update only with role write. `document_access` insert/update/delete only by the document owner. - Mint realtime room tokens in a route handler after the same access check. - Public links use random ids and are revocable; rate-limit invites; validate with zod. ### Performance & SEO Landing is static; dashboard and docs are dynamic and noindex. Lazy-load editors per type. Throttle cursor broadcasts to 20/s. ### Guardrails - Invent all names, orgs and document titles. - Never show a user in presence who lacks access. - Acceptance criteria: (1) two browsers see each other's cursors and edits; (2) sharing with a group grants access to its members; (3) revoking public access blocks the link immediately; (4) viewers cannot edit; (5) dashboard updates when a new document is created elsewhere.