Skip to main content
vibld

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

  1. 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
  2. Editor (after upload): video preview area with hover transport overlay
  3. Timeline below: keyframe thumbnail strip, time ruler with zoom-aware markers, draggable playhead, trim handles with dimmed excluded regions, multiple segments
  4. 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

SampleWhereRatioNeeds
Aatext on background18.42:14.5:1
Aamuted text on background6.55:14.5:1
Aamuted text on card6.31:14.5:1
Aamuted text on secondary surface5.86:14.5:1
Aaneon primary text/indicator on background10.69:14.5:1
Aadark label on neon button10.69:14.5:1
trim handle / playhead on secondary surface9.56:13:1
input border / slider track on card3.23:13: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.

Open the builderAll templatesThis palette on its own