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.
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 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
- Azeret Mono Medium 20px, sentence case
- Body
- Azeret Mono 16px body/helper text, 14px control labels, muted grey 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 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 **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 grey 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.