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.
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
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 gray 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 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
- 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 gray; 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 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 **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 gray 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.