Template
Plainwrite
A lightweight collaborative document editor for small teams: rich text with a floating toolbar, live presence, inline comment threads, autosave, a month-grouped document library and simple writing analytics. It replaces heavier wiki or docs suites for teams of 2-20.
Lightweight collaborative docs editor · 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
Geist's calm, monochrome precision is the brand of this writing app, and few templates use it, so it stays.
- GeistHeadings: headings 70px 600 at -2.1px, section heads 32px
- GeistBody: body 16px, UI 13px
- Sometype MonoFigures and code: counts
Other designs for this product
- Chorusdesk: Real-time collaborative documents starter
- Coquill: Collaborative rich-text documents editor starter
Who it is for
- Small teams of 2-20
- Agencies and design studios
- Teams keeping meeting notes and roadmaps
- Managers tracking writing output
Layout
- White top bar: wordmark left, 'Sign in' and black pill 'Get started' right
- Centered hero: huge 70px product name, gray tagline, black pill CTA
- Grayscale logo strip
- Dark full-width band: pill tab switcher (Rich text editor / Live presence / Comments) with pause, section heading, and a browser-framed app mock (sidebar: New document, Overview, Documents, Analytics, Settings; doc breadcrumb, Saved ✓, word count)
- Auto-advancing demo progress pill
- Dark rounded CTA panel with white pill button
- Footer
- App: overview dashboard, documents library (list/grid, month groups), editor with cover image and emoji icon, comments sidebar, analytics charts, settings/invites
Palette
Minimal, monochrome, calm, confident, modern. Black-and-white restraint that keeps attention on writing.
- background
#ffffff - text
#0a0a0a - dark band
#1a1a1a - muted gray text
#666666 - surface
#f5f5f5 - border
#e5e5e5
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text on background | 19.80:1 | 4.5:1 |
| Aa | muted gray text on background | 5.74:1 | 4.5:1 |
| Aa | muted gray text on muted surface | 5.27:1 | 4.5:1 |
| Aa | light text on black primary button | 18.97:1 | 4.5:1 |
| Aa | white text on dark band | 17.40:1 | 4.5:1 |
| Aa | secondary text on dark band | 6.90:1 | 4.5:1 |
| input border on background | 3.07:1 | 3:1 |
As vibld’s tokens
The palette on the 15+ color tokens vibld styles a project with, each text color 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
- Geist 600, 70px with -2.1px tracking; 32px section heads
- Body
- Geist 400 16px; 13px UI
Monochrome single-family system; the product's calm typography is the brand. Accessibility: body copy 16px or larger at 1.5+ line height with a ~70ch max measure; no text below 12px; weights under 400 only at 32px+; uppercase reserved for short labels with 0.05em+ tracking.
Spacing and imagery
Generous whitespace, ~900px mock inside 1200px container, pill buttons, 10px radius cards, 24px radius dark CTA panel.
Grayscale partner-style logo strip, browser-framed product UI mocks, cover image presets on documents, small avatars for presence.
Components
- Pill tab demo switcher
- Browser-framed product mock
- Logo strip
- Sidebar navigation
- Document library table grouped by month with mini previews
- List/grid toggle
- Search by title/content
- Multi-select batch delete
- Editor with cover image and emoji icon
- Floating bubble toolbar
- Presence avatars and cursors
- Inline comment threads
- Overview stat cards
- Analytics charts with date range filter
Interactions
- Auto-advancing demo tabs with pause
- Select text to format via bubble menu
- Real-time presence indicators
- Comment on selected text, reply, resolve
- Autosave with 'Saved' indicator and word count
- Search filters live
- Batch select and delete with confirm
- Date range filter on analytics
Data
Workspace{id, name}Member{workspace_id, user_id, role: owner|editor|viewer}Document{id, workspace_id, title, emoji, cover, ydoc_state, word_count, author_id, created_at, updated_at}CommentThread{id, document_id, anchor, resolved}Comment{thread_id, author_id, body, created_at}Invite{workspace_id, email, role, token}
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 a template'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 templates) - 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 color 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, labeled 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.
### Goal Build **Plainwrite**, a simple shared-docs tool for small teams (2-20 people) who find full wikis too heavy. Members write in a clean rich-text editor with cover images and emoji icons, see who else is in a document, discuss inline, and never think about saving. A library keeps docs findable and a small analytics view shows writing activity. ### Stack React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix), lucide-react. Tiptap with Collaboration/Cursor extensions over Yjs (provider on Supabase Realtime or a Hocuspocus server), dnd-kit for reordering pinned docs, TanStack Query + TanStack Table for the library, Recharts for analytics, Framer Motion for the landing demo, react-hook-form + zod for settings and invites. Supabase: Auth, Postgres, Realtime presence, Storage for custom covers, Edge Function for invites. ### Pages & layout 1. **Landing**: white nav; massive centered product name, gray tagline, black pill CTA; a grayscale strip of fictional partner wordmarks; a dark band with pill tabs (Editor, Presence, Comments) that auto-advance with a pause button above a browser-framed product mock; a dark rounded CTA panel; footer. 2. **Overview**: totals (documents, comments, words this week), three recent documents, activity list. 3. **Documents**: search (title and content), list/grid toggle, month-grouped table with mini thumbnail, title, author, word count, updated; checkbox multi-select with batch delete. 4. **Editor**: optional cover (six presets or upload) and emoji icon; title; body; breadcrumb, "Saved" state and word count in the header; presence avatars; comments sidebar. 5. **Analytics**: words and documents over time, top authors; range filter 7/30/90 days/all. 6. **Settings**: workspace name, members, roles, invites. ### Design system Monochrome. Tokens: `--background: #ffffff`, `--foreground: #0a0a0a`, `--muted: #f5f5f5`, `--muted-foreground: #666666`, `--border: #e5e5e5`, `--primary: #0a0a0a`, `--primary-foreground: #fafafa`, `--inverse: #1a1a1a`; presence colors from a set of eight. Font: Geist 400/500/600 (Google Fonts) with Sometype Mono for counts; editor body 17px/1.7. Scale 13/16/20/32/70; headings at -0.03em. Radius 10px; pills for buttons; 24px on the CTA panel. Shadows barely there. Motion 200ms; tabs auto-advance every 6s. Add `--input-border: #939393` and dark-band secondary text `#a3a3a3`. ### Components & interactions Bubble toolbar (bold, italic, heading, code, quote, link) appears on selection. Comment flow: select text → "Comment" → thread with replies → resolve; resolved threads collapse. Presence: avatar stack and colored cursor labels. Autosave states: saving, saved, offline. Batch delete: confirm dialog listing count. Empty library state with "New document". Errors show inline banners with retry. ### Data & state Workspace, Member(role), Document(title, emoji, cover, ydoc_state, word_count), CommentThread(anchor as Yjs relative position), Comment, Invite. Analytics computed from document update events or a daily snapshot table. Library filters in URL. Seed ~20 docs (roadmap, meeting notes, onboarding guide) with fictional authors. ### Accessibility Editor toolbar buttons labeled with `aria-pressed`; keyboard shortcuts documented. Auto-rotating demo pauses on hover/focus and reduced motion. Comments panel is a labeled `aside` with headings per thread. Gray text (#666666) passes 4.5:1 on white and on the muted surface at every size. Cover images marked decorative unless custom with alt. Type: body 16px+, line height 1.5+, max ~70ch, nothing under 12px. Verified contrast: body text #0a0a0a on #ffffff = 19.8:1; muted gray text #666666 on #ffffff = 5.74:1; muted gray text #666666 on #f5f5f5 = 5.27:1; light text #fafafa on #0a0a0a = 18.97:1. ### Security RLS by workspace membership: viewers read only; editors create and edit; owners manage members. Enforce read-only for viewers in the collaboration server as well as the UI. Sanitize pasted HTML and comment content with DOMPurify. Invites are expiring single-use tokens sent from an Edge Function. Cover uploads: images ≤5 MB. Batch delete is soft-delete with a 30-day restore window. ### Performance & SEO Lazy-load the editor and analytics; paginate library by month. Use small preview thumbnails. Landing meta/OG, semantic headings; app `noindex`. ### Guardrails - Original copy; fictional logos only -- never real company marks in a logo strip. - No invented customer quotes. - Typed components, no `any`, visible errors. - Done when: two users see each other's presence and edits live; comments anchor to text and resolve; the library groups by month and searches content; batch delete asks for confirmation; viewers cannot edit.