Template
Cutline
A browser-only video trimmer with a neon-on-black editor: drop in a clip, see a thumbnail timeline, drag trim handles to keep one or more segments, and preview playback that skips the cut parts. It is a solid base for prototyping a video SaaS or an internal media tool, with export left as a stub.
Browser video trimmer · 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
Azeret Mono has squared, engineered digits that read like timecode, so the all-monospace editing bay keeps its feel in a face no other template uses.
- Azeret MonoHeadings: headings 20px medium
- Azeret MonoBody: body and helper text 16px, control labels 14px, timecodes 12px
Who it is for
- Developers prototyping video editing products
- Indie SaaS builders
- Product teams validating trimmer UX
- Agencies building media-tool demos
Layout
- Empty state: centered dark card with neon green glow border, upload icon, monospace headline, helper line, green pill 'Choose file' button on near-black canvas
- Editor (after upload): video preview area with hover transport overlay
- Timeline below: keyframe thumbnail strip, time ruler with zoom-aware markers, draggable playhead, trim handles with dimmed excluded regions, multiple segments
- Editor controls bar: play/pause, split/add segment, undo/redo, zoom, export button stub
Palette
dark, technical, focused, electric, sleek. A night-mode editing bay where the neon green signals what's active.
- background
#141414 - card
#181818 - secondary surface
#1f1f1f - text
#ffffff - muted text
#9a9a9a - neon primary
#28e26c - border
#2e2e2e
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | text on background | 18.42:1 | 4.5:1 |
| Aa | muted text on background | 6.55:1 | 4.5:1 |
| Aa | muted text on card | 6.31:1 | 4.5:1 |
| Aa | muted text on secondary surface | 5.86:1 | 4.5:1 |
| Aa | neon primary text/indicator on background | 10.69:1 | 4.5:1 |
| Aa | dark label on neon button | 10.69:1 | 4.5:1 |
| trim handle / playhead on secondary surface | 9.56:1 | 3:1 | |
| input border / slider track on card | 3.23: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
- Azeret Mono Medium 20px, sentence case
- Body
- Azeret Mono 16px body/helper text, 14px control labels, muted gray helper text
All-monospace UI evokes timecode and developer tooling.
Spacing and imagery
Single centered card (~600px) with 24px radius in empty state; editor fills viewport with tight 8px control spacing; pill buttons.
No imagery beyond the user's own video; thumbnails extracted from the clip; neon glow shadows around active elements.
Components
- Glowing upload dropzone card
- Choose file pill button
- Video preview with hover transport overlay
- Keyframe thumbnail strip
- Time ruler
- Draggable playhead
- Trim handles with dimmed out-regions
- Segment list / multi-segment blocks
- Undo/redo buttons
- Zoom slider
- Export button (stub)
- Toasts
Interactions
- Drag-over intensifies neon glow; invalid file type shows toast
- Click video to toggle play; hover shows controls
- Drag trim handles; excluded regions dim
- Scrub playhead with zoom-aware markers
- Gap-skipping playback across selected segments
- Keyboard shortcuts (space, J/K/L, S split, Cmd+Z)
- Undo/redo history
- Spring-scaled buttons and presence transitions
Data
VideoSource{file, objectUrl, duration, width, height}Thumbnail{time, dataUrl}Segment{id, start, end}EditorState{segments[], playhead, zoom, selectedSegmentId, history[], future[]}
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 **Cutline**, a dark, neon-accented video trimmer that runs entirely in the browser. A user drops in a clip, sees a thumbnail timeline, keeps one or more segments by dragging handles, and previews the result with playback that jumps over the removed gaps. Treat it as a strong prototype for a video product. Export is an explicit, pluggable step.
### Stack
React 18 + TypeScript (strict) + Vite, Tailwind CSS, shadcn/ui (Radix: Slider, Tooltip, Dialog) and lucide-react. Use Framer Motion for presence and springy buttons, Sonner for toasts, and Zustand (or useReducer) for editor state with an undo/redo stack. Use the native `<video>` element with canvas frame extraction for thumbnails and `requestAnimationFrame` for the playback supervisor. Wrap export in an interface with an ffmpeg.wasm implementation behind a lazy import. No backend.
### Pages & layout
1. **Empty state**: a near-black canvas with one centered card (about 600px) that has a soft neon glow border, an upload icon, a monospace headline, one helper line and a green pill "Choose file" button. The whole card is a drop target.
2. **Editor**:
- Top bar: file name, duration, and Replace and Export buttons.
- Preview: 16:9 video with a hover overlay (play/pause, current time and total).
- Timeline: time ruler, thumbnail strip, segment blocks with left and right trim handles, dimmed excluded areas and a draggable playhead.
- Controls row: play, split at playhead, delete segment, undo, redo, zoom slider, and a keyboard-shortcut help button.
### Design system
- Tokens: `--background: #141414`, `--card: #181818`, `--secondary: #1f1f1f`, `--muted: #262626`, `--border: #2e2e2e` (decorative), `--input-border: #696969`, `--foreground: #ffffff`, `--muted-fg: #9a9a9a`, `--primary: 142 76% 52%` (≈`#28e26c`), `--primary-fg: #141414`.
- Glow: `box-shadow: 0 0 24px hsl(var(--primary) / .35)`.
- Font: Azeret Mono (or Azeret Mono, then ui-monospace) throughout; 12px timecodes, 14px control labels, 16px body and helper text at line-height 1.5, 20px headings; weights 400+.
- Spacing on a 4px base; timeline track height 64px.
- Radius: card 24px, segments 6px, buttons fully rounded.
- Motion: springs (stiffness 400, damping 30) for button press, 150ms for handle hover.
- Dark only, with every accent derived from one primary token.
### Components & interactions
DropZone (idle, drag-over with stronger glow, invalid type, loading metadata), VideoPreview (buffering spinner, error for unsupported codecs), ThumbnailStrip (skeleton while extracting, progressive fill), TimeRuler (tick density follows zoom), Playhead (drag, click-to-seek), SegmentBlock (selected, hover, min-length guard, collision prevention), TrimHandle (grab cursor, focus ring, 44px hit area), ControlsBar (disabled undo/redo at stack ends), ExportDialog (format and quality, progress, cancel, "export not configured" error). Shortcuts: Space play, S split, Delete remove, Cmd/Ctrl+Z / Shift+Z undo/redo, arrows nudge.
### Data & state
`VideoSource{objectUrl, duration, width, height}`, `Segment{id, start, end}` (seconds, sorted, non-overlapping), and `EditorState{segments, playhead, zoom, selectedId}` with `past[]`/`future[]` snapshots capped at 100 entries. Keep thumbnails in memory as ObjectURLs and revoke them when the video is replaced. The playback supervisor checks on each frame whether `currentTime` has passed a segment's end and seeks to the next start.
### Accessibility
Trim handles and the playhead are sliders (`role="slider"`, `aria-valuenow` in seconds, formatted `aria-valuetext`) that respond to the arrow keys. Neon green on `#141414` is 10.7:1, and green buttons use the dark `--primary-fg` label. Muted gray helper text stays at 5.9:1 or better on every surface. Inputs and the zoom slider track use `--input-border` for 3:1 boundaries. Label every icon button. Honor `prefers-reduced-motion` by disabling springs and glow pulses. Provide a visible shortcut list.
Verified contrast: text: #ffffff on #141414 = 18.4:1; muted: #9a9a9a on #141414 = 6.5:1; dark label on neon: #141414 on #28e26c = 10.7:1.
### Security
All work stays local: accept only `video/*` MIME types, with a size cap (e.g., 1 GB) and a clear message when it is exceeded. Never send media anywhere. Revoke object URLs. Lazy-load ffmpeg.wasm from your own origin and set the COOP/COEP headers it needs. Keep a CSP free of `unsafe-eval` except where the wasm build requires `wasm-unsafe-eval`. There are no secrets in the client.
### Performance & SEO
Extract thumbnails in an OffscreenCanvas or throttled idle callbacks at a low resolution. Virtualize the thumbnail strip at high zoom. Code-split the editor and the export engine. Add a title, meta description, OG image and a single H1 on the empty state.
### Guardrails
- Write fresh copy and royalty-free sample media only; no editor brand names.
- Never upload user media, and don't store it after the tab closes.
- Keep components small and typed; no `any`. Surface codec and export errors visibly.
- Done when: (1) any MP4/WebM loads with thumbnails; (2) several segments can be created, trimmed and deleted with undo/redo; (3) preview playback skips the gaps exactly; (4) every timeline control works by keyboard; (5) the export stub shows a clear, typed extension point.