Template
Quillmark
A privacy-first PDF signing tool that runs entirely in the browser. The user drops in a contract, draws or types a signature, places and resizes it on any page, and downloads the signed file without an account or a server upload. It is aimed at freelancers and small service businesses that sign routine agreements.
Private in-browser document e-signing · App · Small tools and apps · front-end app (local state)
A mock-up of the homepage, drawn from this design’s layout, palette and typefaces. A build follows the full prompt below.
Start from this templateRead the build prompt
Typefaces
Public Sans is a plain, system-like neutral sans that keeps the desk tool quiet; the three scripts give distinct signature styles, and La Belle Aurore looks more like a real pen signature than Caveat.
- Public SansHeadings: two-line title 36px bold
- Public SansBody: interface text 16px, card titles 18px bold
- Dancing ScriptHandwriting: typed signature style: neat cursive
- Homemade AppleHandwriting: typed signature style: loose handwriting
- La Belle AuroreHandwriting: typed signature style: quick pen signature
Who it is for
- Freelancers and consultants signing client agreements
- Solo founders handling NDAs
- Small service businesses
- Privacy-conscious users avoiding e-sign subscriptions
Layout
- No nav; split hero: bold two-line title + subcopy + three icon bullet points (no sign-in, draw or type, instant download) left, line-art document illustration with signature box right
- Light grey band containing a large white card with dashed-border dropzone (circle plus icon, instruction, size limit) and privacy note
- Row of three centered feature cards with line icons (Free & Private, Easy Signing, Instant Download)
- After upload: toolbar with zoom/undo/clear/download, vertically stacked PDF pages, signature pad modal, draggable signature overlays
Palette
trustworthy, minimal, calm, utilitarian, private. Feels like a quiet desk tool rather than a sales-driven e-sign platform.
- background
#ffffff - band background
#fafafa - heading text
#111827 - body text
#4b5563 - primary green
#11813b - border / dashed
#e5e7eb - icon circle
#e5e7eb
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | heading text on background | 17.74:1 | 4.5:1 |
| Aa | body text on background | 7.56:1 | 4.5:1 |
| Aa | body text on band | 7.24:1 | 4.5:1 |
| Aa | white label on primary green button | 4.97:1 | 4.5:1 |
| Aa | white label on danger button | 4.83:1 | 4.5:1 |
| dashed dropzone / input border on white | 3.34:1 | 3:1 | |
| green focus ring / drag-over border on white | 4.97:1 | 3:1 | |
| Aa | icon on icon circle | 14.33:1 | 4.5: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
- System UI sans Bold 36px, tight two-line title (the system face is not on Google Fonts; a vibld project loads Public Sans)
- Body
- System UI 16px grey; card titles 18px bold with slight tracking (the system face is not on Google Fonts; a vibld project loads Public Sans)
Default system stack keeps it neutral and fast; weight contrast carries hierarchy.
Spacing and imagery
Narrow ~770px content column, generous white space, cards 12px radius with soft shadows, dashed dropzone with rounded corners.
Monochrome line-art illustration of a document with checkboxes, pen, lock and download arrow; lucide-style line icons; no photos.
Components
- Split hero with icon bullets
- Line-art illustration
- Dashed dropzone card
- Privacy note
- Feature cards (3)
- PDF page viewer (multi-page)
- Signature pad modal (draw / type tabs)
- Draggable, resizable signature overlay
- Zoom controls
- Undo / clear all actions
- Download signed PDF button
- Date stamp field
Interactions
- Drag-and-drop or click to upload with drag-over highlight
- Reject non-PDF or >10MB files with message
- Draw signature with undo stroke history; or type with script font
- Drag signature onto any page, resize with handles
- Zoom in/out for precise placement
- Undo last placement or clear all
- Session persistence across refresh
- Download triggers flattened PDF with success toast
Data
DocumentSession{fileName, pdfBytes (IndexedDB), pageCount, createdAt}Signature{id, kind draw|type, dataUrl, text?, font?}Placement{id, signatureId, page, x, y, width, height}DateStamp{page, x, y, value}
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 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.
### Goal
Build **Quillmark**, a browser-only tool for signing PDFs. A freelancer or small-business owner uploads an agreement, creates a signature once, places it wherever it's needed on any page, and downloads the signed file. The document never leaves the device, and there is no account.
### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix: Dialog, Tabs, Tooltip) and lucide-react. Use react-pdf (pdf.js) for rendering, pdf-lib to embed signatures and flatten the output, react-dropzone for upload, react-draggable or dnd-kit plus a resize handle for placements, `signature_pad` for drawing, and idb-keyval to keep the session in IndexedDB. No backend.
### Pages & layout
1. **Landing / upload** (single route):
- Split hero: a bold two-line title, a short subcopy and three icon bullets on the left; a line-art document illustration on the right.
- A light grey band with a large white card holding a dashed dropzone (round plus button, instruction, "PDF up to 10 MB") and a one-line privacy note.
- Three feature cards with line icons.
2. **Editor** (after upload): a sticky toolbar (file name, page count, zoom −/+, Add signature, Add date, Undo, Clear all, Download), a scrollable column of rendered pages, and a right rail listing saved signatures to reuse.
3. **Signature dialog**: Draw and Type tabs, a canvas with Undo stroke and Clear, typed name with a choice of three script fonts, and Save.
### Design system
- Tokens: `--background: #ffffff`, `--band: #fafafa`, `--heading: #111827`, `--body: #4b5563`, `--primary: #11813b` (download and confirm), `--border: #e5e7eb` (decorative card edges), `--input-border: #838da0` for the dashed dropzone and inputs, `--danger: #dc2626` for Clear all.
- Fonts: the system UI stack or Public Sans for the interface (body 16px at line-height 1.6, nothing below 12px); La Belle Aurore, Dancing Script and Homemade Apple (Google Fonts) for typed signatures.
- Spacing on a 4px base; content max width 768px, editor full width.
- Radius: cards 12px, dropzone 12px with a 2px dashed `--input-border`, buttons 8px.
- Shadows: `0 4px 16px -4px rgb(0 0 0 / .08)`.
- Motion: 150ms hover, 200ms dialog fade/scale.
- Light theme only; the documents themselves are white.
### Components & interactions
Dropzone (idle, drag-over with green border, rejected with the reason, loading spinner while pdf.js parses), PageCanvas (lazy-render pages near the viewport, loading skeleton), SignaturePad (stroke undo, empty-state hint, disabled Save until something is drawn), PlacementBox (drag, resize with corner handles, delete button, selected outline, arrow-key nudge), ZoomControls, Toolbar buttons with tooltips and disabled states, DownloadButton (processing state, then a success toast), plus an error banner for encrypted or corrupt PDFs.
### Data & state
State lives in a Zustand store or a reducer: `session {fileName, pageCount}`, `signatures[] {id, kind, dataUrl}`, `placements[] {id, signatureId, page, x, y, w, h}` with coordinates normalized 0-1 per page so zoom never breaks them. Persist the PDF bytes and state in IndexedDB and offer "Start over" to wipe them.
### Accessibility
The drawing canvas can't be operated by keyboard, so the Type tab must be a full alternative. Placements must be focusable, movable with arrow keys (Shift for larger steps) and deletable with Delete. Announce placement actions in a live region. Toolbar buttons need text labels or `aria-label`s. Give each rendered page an accessible name ("Page 2 of 5"). The primary green is set at `#11813b` so white button labels pass AA.
Verified contrast: heading: #111827 on #ffffff = 17.7:1; body: #4b5563 on #ffffff = 7.6:1; white on primary: #ffffff on #11813b = 5.0:1.
### Security
All processing stays local, so say so and make sure no network calls carry document data (verify in devtools and add a strict CSP with `connect-src 'self'`). Validate the upload's MIME type and `%PDF` header, and cap it at 10 MB. Reject encrypted PDFs gracefully. Load pdf.js's worker from your own build, not a third-party CDN. Clear IndexedDB on "Start over". State clearly that the output is a visual signature, not a certified digital signature.
### Performance & SEO
Code-split the editor (pdf.js and pdf-lib) from the landing view. Virtualize page rendering and cache page bitmaps per zoom level. Add meta and OG tags plus one H1. Target Lighthouse 95+ on the landing view.
### Guardrails
- Write fresh copy and your own line illustration; no e-sign brand names.
- Make no legal-validity claims beyond what the tool actually does.
- Never upload or log document contents.
- Keep components small and typed; no `any`. Show errors visibly.
- Done when: (1) a 20-page PDF renders and scrolls smoothly; (2) one signature can be placed on several pages and resized; (3) the downloaded PDF shows the signatures in the correct positions in other viewers; (4) refreshing restores the session; (5) keyboard users can place and move a typed signature.