Template
Plotwick
An export dialog in a collaborative mapping tool. Users choose a layout, toggle view, legend, scale, branding and output options, and see a live print-style preview of the map with title, legend, projection, scale bar and locator inset before exporting as an image or PDF.
Map export modal with live print-layout preview · App screen: import export · Small tools and apps · front-end app (local state)
A mock-up of the screen, drawn from its layout, palette and typefaces. A build follows the full prompt below.
Start from this screenRead the build prompt
Typefaces
The catalog's own faces. A screen composed into a template is drawn in that template's typefaces.
- InterHeadings: Inter 600, 20px modal title; 18px map title in preview
- InterBody: Inter 400 16px/1.5 in settings
Patterns
- large modal over dimmed app
- left settings column with accordion options
- live WYSIWYG preview pane
- print layout with title, legend, scale bar, north arrow and inset map
- layout preset select
- cancel / primary export pair
States it is designed for
- default preview
- rendering preview (spinner overlay on map frame)
- exporting (progress toast)
- export failed (retry)
- legend empty (no visible layers → message)
- logo upload invalid type
- very long title (wraps to two lines, then truncates with tooltip)
Who it is for
- urban planners
- GIS analysts
- environmental consultants
Layout
- dimmed app behind (scrim)
- modal (~90vw × 90vh, max 1200px): left column (~300px) and right preview pane
- left: title, description, Layout select, 'Options' header strip, accordion rows (View, Legend, Scale, Branding, Export), bottom Cancel (outlined) and Export (blue) buttons
- right: small 'Preview' label, framed page with title bar, map area, right legend column (swatches + labels), projection text, scale bar, north arrow, inset locator map
- mobile: modal becomes full screen with Options above a collapsible preview
Palette
Precise and cartographic; neutral chrome lets the map colours lead.
- modal surface
#ffffff - preview pane
#f1f3f5 - primary text
#1a1d21 - secondary text
#5a6270 - primary button
#1463ff - options strip
#eef0f3 - input border
#8a919c - overlay: high class
#d9546a - overlay: mid class
#e5c193 - scrim
#0f1115 - page frame
#1a1d21
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text | 16.91:1 | 4.5:1 |
| Aa | muted text | 6.15:1 | 4.5:1 |
| Aa | export button label | 4.93:1 | 4.5:1 |
| Aa | options label on strip | 5.38:1 | 4.5:1 |
| input border | 3.18:1 | 3:1 | |
| focus ring | 4.93:1 | 3:1 | |
| page frame on pane | 15.20: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
- Inter 600, 20px modal title; 18px map title in preview
- Body
- Inter 400 16px/1.5 in settings
Preview legend text 12px (minimum) scaled with the page; 'Preview' and 'Options' labels 12px uppercase 600 with 0.08em tracking.
Spacing and imagery
Modal radius 12px, padding 24px; accordion rows 44px with 1px dividers; preview page has 1.5px frame and 12px inner padding; legend column 180px.
Satellite-style basemap with semi-transparent thematic overlay classes; small north arrow glyph; inset locator map with a highlighted extent box. Use generic or self-generated basemap tiles.
Components
- ExportModal
- LayoutSelect (standard, landscape, portrait, poster)
- OptionsAccordion (View, Legend, Scale, Branding, Export)
- PreviewPane
- PrintPage (TitleBar, MapFrame, LegendPanel, ProjectionNote, ScaleBar, NorthArrow, InsetMap)
- ExportFormatSelect (PNG, PDF, SVG) + DPI
- ProgressToast
Interactions
- every option updates the preview within 200ms
- clicking the preview title edits it inline
- Legend accordion toggles layers and reorders legend items
- Branding adds a logo upload and footer text
- Export renders server-side or in a worker and downloads; Cancel or Escape closes
- preview zoom-to-fit and 100% toggle
Data
ExportSettings{layout (standard|landscape|portrait|poster), title, show_legend, legend_order string[], show_scale, units (metric|imperial), show_north, show_inset, branding {logo_url, footer}, format (png|pdf|svg), dpi (150|300)}MapLayer{id, name, visible, style {fill, opacity}, classes {label, color}[]}
Guardrails
Experience
- Make the preview a faithful WYSIWYG of the exported file (same fonts, proportions).
- Keep the options collapsed by default with sensible defaults so one click exports.
- Place Export bottom-left under the options where the eye finishes, with Cancel beside it.
- Scale legend text with the page but never below 12px at 100%.
- Remember the last used settings per map.
Accessibility
- Modal is a dialog with labelled title and description, focus trapped, Escape closes.
- Accordion uses buttons with aria-expanded and controls.
- Legend swatches are paired with text labels; map classes are distinguishable by pattern option for colour-blind users.
- Preview has a text summary (title, layers, scale) for screen readers.
- Scrim behind the modal is 60% dark; modal content is on solid white.
Security
- Validate uploaded logo (PNG/SVG under 500 kB); sanitise SVG before rendering.
- Escape user-entered title and footer text.
- Generate exports client-side or via a signed request; never expose tile provider keys in exported metadata.
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 **Plotwick**, the map export dialog of a web mapping tool. The dialog pairs a compact options column with a live print-layout preview (title, map, legend, projection, scale bar, north arrow, inset) and exports PNG, PDF or SVG entirely in the browser.
### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Dialog, Accordion, Select, Switch, Input), lucide-react, react-hook-form + zod for settings, Motion for the modal. Use an open-source web map renderer with an open basemap style, and a client-side PDF/canvas export utility.
### Pages & layout
1. **Map view** (mock) with a Share/Export button that opens the modal.
2. **Export modal**: options column + preview pane.
3. Mobile: full-screen sheet, options first, preview collapsible.
### Design system
- Colors: `--surface: #ffffff` (modal surface), `--pane: #f1f3f5` (preview pane), `--fg: #1a1d21` (primary text), `--muted: #5a6270` (secondary text), `--primary: #1463ff` (primary button), `--strip: #eef0f3` (options strip), `--input-border: #8a919c` (input border), `--map-high: #d9546a` (overlay: high class), `--map-mid: #e5c193` (overlay: mid class), `--scrim: #0f1115` (scrim), `--frame: #1a1d21` (page frame).
- Fonts: Inter 600, 20px modal title; 18px map title in preview for headings; Inter 400 16px/1.5 in settings for body. Preview legend text 12px (minimum) scaled with the page; 'Preview' and 'Options' labels 12px uppercase 600 with 0.08em tracking.
- Spacing: Modal radius 12px, padding 24px; accordion rows 44px with 1px dividers; preview page has 1.5px frame and 12px inner padding; legend column 180px.
- Radius: 12px modal, 6px inputs and buttons, 0 for the print page (it is paper).
- Shadows: modal 0 24px 48px rgba(0,0,0,0.25).
- Scrim: #0f1115 at 60% opacity.
- Motion: modal 200ms scale-fade; preview updates cross-fade 150ms; off under reduced motion.
### Components & interactions
ExportModal, LayoutSelect, OptionsAccordion, PreviewPane, PrintPage, TitleBar, MapFrame, LegendPanel, ScaleBar, NorthArrow, InsetMap, ExportFormatSelect, ProgressToast.
Interactions: every option updates the preview within 200ms; clicking the preview title edits it inline; Legend accordion toggles layers and reorders legend items; Branding adds a logo upload and footer text; Export renders server-side or in a worker and downloads; Cancel or Escape closes; preview zoom-to-fit and 100% toggle.
States to build: default preview; rendering preview (spinner overlay on map frame); exporting (progress toast); export failed (retry); legend empty (no visible layers → message); logo upload invalid type; very long title (wraps to two lines, then truncates with tooltip).
### Data & state
All state is local: settings in a react-hook-form store, persisted per map id in localStorage (try/catch). Seed a map 'Soil types, riverside district' with one building layer and six soil classes with invented labels.
Model: `ExportSettings{layout (standard|landscape|portrait|poster), title, show_legend, legend_order string[], show_scale, units (metric|imperial), show_north, show_inset, branding {logo_url, footer}, format (png|pdf|svg), dpi (150|300)}`; `MapLayer{id, name, visible, style {fill, opacity}, classes {label, color}[]}`.
### Accessibility
Modal is a dialog with labelled title and description, focus trapped, Escape closes. Accordion uses buttons with aria-expanded and controls. Legend swatches are paired with text labels; map classes are distinguishable by pattern option for colour-blind users. Preview has a text summary (title, layers, scale) for screen readers. Scrim behind the modal is 60% dark; modal content is on solid white.
Verified contrast: body text: #1a1d21 on #ffffff = 16.91:1; muted text: #5a6270 on #ffffff = 6.15:1; export button label: #ffffff on #1463ff = 4.93:1; options label on strip: #5a6270 on #eef0f3 = 5.38:1; input border: #8a919c on #ffffff = 3.18:1; focus ring: #1463ff on #ffffff = 4.93:1; page frame on pane: #1a1d21 on #f1f3f5 = 15.2:1.
### Security
Validate uploaded logo (PNG/SVG under 500 kB); sanitise SVG before rendering. Escape user-entered title and footer text. Generate exports client-side or via a signed request; never expose tile provider keys in exported metadata. No backend. Sanitise uploaded SVG logos (strip scripts and external references) and escape all text before drawing to canvas.
### Performance & SEO
Debounce preview re-render 150ms; render exports in a Web Worker/OffscreenCanvas where available; cap DPI at 300. App route noindex.
### Guardrails
- Make the preview a faithful WYSIWYG of the exported file (same fonts, proportions).
- Keep the options collapsed by default with sensible defaults so one click exports.
- Place Export bottom-left under the options where the eye finishes, with Cancel beside it.
- Scale legend text with the page but never below 12px at 100%.
- Remember the last used settings per map.
- Write all copy fresh; use invented people, companies and numbers only. No real brands, logos, wordmarks or third-party product names anywhere in the UI or seed data.
- Do not trace or copy any existing product's layout assets, icons or illustrations; draw generic ones.
- Acceptance criteria:
- [ ] Changing layout or options updates the preview
- [ ] Legend reflects visible layers and order
- [ ] PNG and PDF exports match the preview
- [ ] Keyboard users can open, operate and close the modal
- [ ] Settings persist per map