Skip to main content
vibld

Template

Pixelmere

The assets section of a headless content management system. Content teams browse, filter and upload images through saved views (banners, product shots, videos, logos), switch between list and grid, and pick assets for entries. It is the media library for a multi-locale content project.

Headless CMS media asset library grid with saved views · App screen: import export · Small tools and apps · full-stack app (auth + DB)

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, 16px view title; 14px pane headers
  • InterBody: Inter 400 16px/1.5 (15px in captions and lists)

Patterns

  • environment banner strip in top bar
  • icon+label primary rail
  • secondary pane with saved custom views
  • list/grid view toggle
  • filter chip with removable condition
  • locale selector beside search
  • thumbnail grid with filename captions
  • sort dropdown with select-all

States it is designed for

  • grid populated
  • list view
  • no results for filter (clear-filter action)
  • empty view (upload CTA)
  • uploading with per-file progress tiles
  • processing thumbnails (shimmer)
  • unsupported file type error
  • bulk selection active
  • permission: viewers cannot upload or delete

Who it is for

  • content editors
  • e-commerce merchandisers
  • front-end developers maintaining content models

Layout

  1. top bar: project badge and name, environment indicator on a pale green strip, global search with icons, AI-assist button, help, messages, notifications, avatar
  2. primary rail (~180px): Home, Schema, Content, Assets active, API playground
  3. secondary pane (~220px, collapsible): Assets header with add-folder icon; Schedule group (Entries, Releases); Custom views folder (Banners, Main images, 360 images, Action shots active, Videos, Logos); Default views (Asset)
  4. main header: model chip, view name, model tag, overflow; list/grid toggle, View menu with dot indicator, purple Upload, outlined Add entry
  5. filter row: locale select, search, condition chip 'Asset type is …' with clear, filter button
  6. sort dropdown and select-all checkbox
  7. 4-column thumbnail grid (fluid 2–6 columns) with filename captions (extension muted)
  8. mobile: rail becomes bottom tabs; secondary pane becomes a views sheet

Palette

Tidy and professional with a single violet accent; photos provide all the colour.

  • page background#ffffff
  • environment strip#e6f4ea
  • environment text#1d6a39
  • primary text#1f2330
  • secondary text#5f6573
  • active view fill#eef0ff
  • active view text#4a3fd1
  • upload button#5b4de0
  • input border#8a8fa0
  • thumbnail frame#e6e8ee

Every checked pair, measured again

SampleWhereRatioNeeds
Aabody text15.66:14.5:1
Aamuted caption5.84:14.5:1
Aaenvironment text5.83:14.5:1
Aaactive view text6.34:14.5:1
Aaupload button label5.86:14.5:1
input border3.22: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
Inter 600, 16px view title; 14px pane headers
Body
Inter 400 16px/1.5 (15px in captions and lists)

Folder labels 12px uppercase 500 with 0.06em tracking; filename extension in muted colour; model tag in Inter 13px muted.

Spacing and imagery

Medium-dense: rail rows 36px; pane rows 32px; grid gap 16px; thumbnails 4:3 with 6px radius and 1px frame; header 56px.

User-uploaded photos in the grid (use generic placeholder scenes, e.g. landscapes and product shots from a seeded set); line icons elsewhere.

Components

  • TopBar (ProjectBadge, EnvironmentStrip, GlobalSearch, AssistButton)
  • PrimaryRail
  • ViewsPane (groups, custom views, default views)
  • AssetHeader (model chip, view title, ViewToggle, ViewMenu, Upload, AddEntry)
  • FilterBar (LocaleSelect, SearchInput, ConditionChip, FilterButton)
  • SortSelect + SelectAll
  • AssetGrid / AssetTable
  • AssetCard (thumbnail, filename)
  • UploadDialog
  • AssetDetailSheet

Interactions

  • click thumbnail opens a detail sheet (preview, metadata, locales, usage)
  • checkbox appears on hover/focus for multi-select; shift-click selects a range
  • bulk actions bar appears when items are selected (move, publish, delete)
  • drag files onto the grid to upload
  • saving the current filter creates a custom view
  • pane collapses with its chevron button

Data

  • Asset{id, project_id, environment, file_name, mime_type, width, height, size_bytes, alt_text jsonb (per locale), asset_type (enum), created_by, created_at, stage (draft|published)}
  • SavedView{id, project_id, name, folder (custom|default), filters jsonb, sort}
  • Environment{id, project_id, name (master|staging…)}
  • AssetUsage{asset_id, entry_id, field}

Guardrails

Experience

  • Always show which environment you are in, in the top bar strip.
  • Keep saved views one click away and show the active view name as the page title.
  • Render the filter as readable chips ('Asset type is Action shot') that can be removed individually.
  • Mute file extensions so names scan faster.
  • Require alt text per locale before an image can be published.

Accessibility

  • Grid is a list of buttons/links with the filename and alt text as accessible names.
  • Selection checkboxes are visible on focus, not only hover.
  • View toggle is a labelled radio group.
  • Filter chips have 'Remove filter' buttons with names.
  • Detail sheet traps focus and restores it to the thumbnail.

Security

  • RLS: assets and views scoped to project members and environment; only editors upload or delete.
  • Validate MIME type by sniffing, cap size, strip EXIF location data on upload.
  • Serve originals via signed URLs; public CDN only for published assets.
  • Soft-delete with a 30-day restore and audit entries.

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 **Pixelmere**, the media library of a headless CMS. Editors browse assets through saved views, filter by type and locale, switch between grid and list, upload by drag and drop, and open a detail sheet to edit per-locale alt text and see where an asset is used.

### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui (ToggleGroup, Select, Popover, Sheet, Checkbox, DropdownMenu), lucide-react, TanStack Query and Table, react-hook-form + zod, date-fns. Supabase Auth, Postgres and Storage with image transforms for thumbnails.

### Pages & layout
1. **CMS shell**: top bar with environment strip, primary rail.
2. **/assets/views/:viewId**: views pane, header, filter bar, grid or table.
3. **Asset detail sheet**.
4. **Upload dialog**.
5. Responsive: pane collapses <1280px; rail to bottom tabs <768px.

### Design system
- Colors: `--bg: #ffffff` (page background), `--env: #e6f4ea` (environment strip), `--env-fg: #1d6a39` (environment text), `--fg: #1f2330` (primary text), `--muted: #5f6573` (secondary text), `--view-active: #eef0ff` (active view fill), `--view-fg: #4a3fd1` (active view text), `--primary: #5b4de0` (upload button), `--input-border: #8a8fa0` (input border), `--thumb: #e6e8ee` (thumbnail frame).
- Fonts: Inter 600, 16px view title; 14px pane headers for headings; Inter 400 16px/1.5 (15px in captions and lists) for body. Folder labels 12px uppercase 500 with 0.06em tracking; filename extension in muted colour; model tag in Inter 13px muted.
- Spacing: Medium-dense: rail rows 36px; pane rows 32px; grid gap 16px; thumbnails 4:3 with 6px radius and 1px frame; header 56px.
- Radius: 6px thumbnails, buttons and inputs; 8px sheets.
- Shadows: sheet and dropdowns only.
- Motion: 150ms hover lift on thumbnails (translateY -1px); shimmer for processing; none under reduced motion.

### Components & interactions
TopBar, EnvironmentStrip, PrimaryRail, ViewsPane, AssetHeader, ViewToggle, FilterBar, ConditionChip, SortSelect, AssetGrid, AssetCard, AssetTable, BulkActionBar, UploadDialog, AssetDetailSheet.

Interactions: click thumbnail opens a detail sheet (preview, metadata, locales, usage); checkbox appears on hover/focus for multi-select; shift-click selects a range; bulk actions bar appears when items are selected (move, publish, delete); drag files onto the grid to upload; saving the current filter creates a custom view; pane collapses with its chevron button.

States to build: grid populated; list view; no results for filter (clear-filter action); empty view (upload CTA); uploading with per-file progress tiles; processing thumbnails (shimmer); unsupported file type error; bulk selection active; permission: viewers cannot upload or delete.

### Data & state
Views store filter JSON applied server-side. Grid uses cursor pagination (48 per page) with infinite scroll. Seed a project 'Trailcraft Bikes' (invented) with 60 placeholder images across six asset types and two locales.

Model: `Asset{id, project_id, environment, file_name, mime_type, width, height, size_bytes, alt_text jsonb (per locale), asset_type (enum), created_by, created_at, stage (draft|published)}`; `SavedView{id, project_id, name, folder (custom|default), filters jsonb, sort}`; `Environment{id, project_id, name (master|staging…)}`; `AssetUsage{asset_id, entry_id, field}`.

### Accessibility
Grid is a list of buttons/links with the filename and alt text as accessible names. Selection checkboxes are visible on focus, not only hover. View toggle is a labelled radio group. Filter chips have 'Remove filter' buttons with names. Detail sheet traps focus and restores it to the thumbnail.
Verified contrast: body text: #1f2330 on #ffffff = 15.66:1; muted caption: #5f6573 on #ffffff = 5.84:1; environment text: #1d6a39 on #e6f4ea = 5.83:1; active view text: #4a3fd1 on #eef0ff = 6.34:1; upload button label: #ffffff on #5b4de0 = 5.86:1; input border: #8a8fa0 on #ffffff = 3.22:1.

### Security
RLS: assets and views scoped to project members and environment; only editors upload or delete. Validate MIME type by sniffing, cap size, strip EXIF location data on upload. Serve originals via signed URLs; public CDN only for published assets. Soft-delete with a 30-day restore and audit entries. RLS per table: `assets` select for project members in allowed environments, insert/update/delete for `editor` role; `saved_views` select for members, write for creator or admins; `asset_usage` read-only to members, maintained by triggers.

### Performance & SEO
Request thumbnails at 2x the rendered size via transforms; lazy-load images with explicit dimensions; virtualise over 300 items. CMS routes noindex.

### Guardrails
- Always show which environment you are in, in the top bar strip.
- Keep saved views one click away and show the active view name as the page title.
- Render the filter as readable chips ('Asset type is Action shot') that can be removed individually.
- Mute file extensions so names scan faster.
- Require alt text per locale before an image can be published.
- 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:
  - [ ] Saved views filter the grid and set the title
  - [ ] Filter chips can be removed individually
  - [ ] Grid/list toggle persists
  - [ ] Uploads show progress tiles and processing shimmer
  - [ ] Images without alt text cannot be published

Open the builderAll templatesThis palette on its own