Template
Pinwall
A spatial mood-board tool where users drop, arrange, resize and rotate images and text notes on an infinite dot-grid canvas, and can generate new images from prompts. A dashboard holds multiple private boards. It serves creatives assembling visual references for brands, shoots and projects.
Infinite-canvas moodboard app · App · Small tools and apps · full-stack app (auth + DB)
Who it is for
- Brand and graphic designers
- Art directors and stylists
- Content planners
- Hobbyists keeping inspiration archives
Layout
- Landing: infinite dot-grid canvas with scattered, rounded image cards (one shown selected with handles)
- Centered frosted white card with huge wordmark, tagline, black 'Get Started' button
- Auth screens (email + Google)
- Dashboard: grid of board thumbnails with title and timestamp, create/rename/reorder/delete
- Board canvas: full-screen pannable/zoomable dot grid, floating bottom tool dock, context menu, AI generate panel
Palette
Airy, editorial, playful, tactile, minimal. Feels like pinning prints on an endless white studio wall.
- background
#fafafa - text / primary
#0a0a0a - card
#ffffff - muted
#f2f2f2 - border
#e6e6e6 - selection blue
#6b7fe0 - muted text
#5c5c5c - input border
#919191
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text on background | 18.97:1 | 4.5:1 |
| Aa | text on floating card/panel | 19.80:1 | 4.5:1 |
| Aa | muted meta text on background | 6.41:1 | 4.5:1 |
| Aa | muted meta text on muted surface | 5.97:1 | 4.5:1 |
| Aa | white on black primary button | 19.80:1 | 4.5:1 |
| selection handles / focus ring on card | 3.66:1 | 3:1 | |
| selection handles / focus ring on background | 3.51:1 | 3:1 | |
| input border on card | 3.15:1 | 3:1 | |
| Aa | dark theme: text on inverted background | 18.97:1 | 4.5:1 |
| Aa | dark theme: muted text on inverted background | 7.85: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
- Display
- Albert Sans 600 at 96px with very tight tracking (-0.05em)
- Body
- Albert Sans 400 16px
One clean grotesk; the photos supply all color and personality
Spacing and imagery
Canvas-first, edge-to-edge; floating UI with 10px radius, soft large shadows; image cards ~12px radius; dot grid ~24px pitch
Fashion portraits, painterly illustrations, florals and pets as full-color image tiles with rounded corners and drop shadows; UI is monochrome.
Components
- Infinite dot-grid canvas
- Image item with resize/rotate handles
- Selection bounding box
- Text note item
- Floating bottom tool dock
- Zoom controls
- Right-click context menu
- AI prompt panel with loading state
- Board thumbnail card
- Create-board button
- Auth forms
- Theme toggle
Interactions
- Pan by drag/space-drag, zoom with wheel/pinch
- Drag images from desktop onto canvas to upload
- Resize and rotate via corner handles
- Double-click text to edit in place
- Copy/paste and delete via shortcuts
- Undo/redo stack
- Autosave with subtle saved indicator
- Board reordering via drag on dashboard
- AI generation shows placeholder shimmer then drops image
Data
Board{id, user_id, title, position, thumbnail_url, updated_at}CanvasItem{id, board_id, type(image|text), x, y, width, height, rotation, z_index, src, text, style}Upload{path, mime, size}Profile{id, theme}
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 **Pinwall**, a spatial mood-board app for designers and stylists. Users collect images and short notes on an infinite canvas, arrange them freely, and generate extra references from text prompts. A dashboard keeps several private boards. The core job: let people think visually by placing things next to each other.
### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (Radix), lucide-react. Canvas rendering with plain DOM + CSS transforms (or react-konva if you prefer); dnd-kit for dashboard board reordering; TanStack Query for boards; zod for item validation; Framer Motion for UI panels. Supabase: Auth (email + Google), Postgres (boards, items), Storage (uploaded and generated images), Edge Function that calls an image-generation API.
### Pages & layout
1. **Landing** – the page itself is a canvas: dot-grid background, 8–10 scattered rounded image tiles (one shown selected with handles), centered white card with a very large wordmark, one-line tagline and black "Get started" button.
2. **Auth** – sign in/up, email verification notice.
3. **Dashboard** – board grid (thumbnail, title, "edited 2h ago"), new-board tile, rename inline, delete with confirm, drag to reorder.
4. **Board** – full-viewport canvas; floating bottom dock (select, hand, text, upload, generate, zoom); top-left back + board title; right-click context menu; generate panel with prompt textarea.
### Design system
Monochrome UI, colorful content. `--background: #fafafa`, `--foreground: #0a0a0a`, `--card: #ffffff`, `--muted: #f2f2f2`, `--border: #e6e6e6`, `--selection: #6b7fe0` (handles, selection box, focus ring), `--muted-foreground: #5c5c5c`, `--input-border: #919191`; `--border` only for decorative hairlines. Dark theme: `--background: #0a0a0a`, `--foreground: #fafafa`, `--muted-foreground: #a3a3a3`. Font: Albert Sans (400/600) with system-ui fallback; display 96px with -0.05em tracking; UI text 14-16px, tooltips and timestamps 12px minimum, line-height 1.5. Radius 10px panels, 12px image tiles, 6px buttons. Shadows `0 10px 30px rgb(0 0 0 / .08)`. Dot grid: 1px dots at 24px spacing, #d4d4d4. Motion 120–200ms ease-out; dark theme inverts neutrals.
### Components & interactions
CanvasViewport (pan/zoom with bounds), CanvasItem (idle/hover/selected/dragging/locked), SelectionBox with 8 handles + rotate knob, TextNote (display/editing), ToolDock (active tool state, tooltips with shortcuts), ContextMenu, GeneratePanel (idle/loading shimmer/error/retry), UploadDropzone overlay, SaveIndicator (saving/saved/offline), BoardCard, EmptyBoard hint ("Drop images or press T for text"). Undo/redo history in a reducer; keyboard shortcuts V, H, T, Cmd+Z, Cmd+C/V, Delete.
### Data & state
`boards` and `canvas_items` tables; item transforms held in local state and debounced-saved (500ms). Storage path `userId/boardId/file`. Seed a demo board with ~10 CC0-style placeholder images and two notes.
### Accessibility
Provide a keyboard mode: Tab cycles items, arrow keys nudge (Shift = 10px), +/- resize, R rotates; announce position changes via live region. Every image item requires alt text (prompt text or user caption). Dock buttons have labels and tooltips. Contrast of UI text is near-black on white. Respect reduced motion (no inertia panning). Dashboard reorder also via menu "Move left/right". Verified contrast: body text #0a0a0a on #fafafa = 18.9:1; muted meta text #5c5c5c on #fafafa = 6.4:1; white #ffffff on #0a0a0a = 19.8:1; selection handles / focus ring #6b7fe0 on #ffffff = 3.6:1; dark theme: text #fafafa on #0a0a0a = 18.9:1.
### Security
RLS on `boards` and `canvas_items`: owner-only via `user_id = auth.uid()` (items joined through board). Storage bucket private with per-user folder policies; signed URLs for display. Upload limits: image MIME only (jpeg/png/webp/gif), ≤10 MB, validated client and server. The generation Edge Function holds the AI API key, validates prompts with zod, enforces per-user rate limits and moderation. Sanitize text notes (plain text only).
### Performance & SEO
Virtualize off-screen items; generate thumbnails for tiles; use `will-change: transform` only while dragging. Lazy-load the canvas route. Landing gets meta/OG tags; app routes `noindex`.
### Guardrails
- Placeholder imagery only (generated or CC0); no brand logos.
- No fake testimonials.
- Don't keep deleted uploads; purge storage on item delete.
- Small typed components, no `any`, visible save/generation errors.
- Done when: a user can create a board, upload by drag, move/resize/rotate an item by mouse and keyboard, undo it, generate an image, reload and see everything persisted, and another user cannot open that board.