Template
Sandbar
A developer playground where a builder configures an AI assistant (name, instructions, model, tools, files) on the left and immediately test-chats with it in a thread on the right. It shortens the loop between editing a system prompt and seeing how the assistant responds.
AI assistant playground with config panel and test thread · App screen: playground · 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, 20px page title, -0.01em tracking
- InterBody: Inter 400/500, 16px inputs and body, 14px labels (600), 13px helper captions; line-height 1.5
Patterns
- icon-only left rail
- two-pane config + preview layout
- labelled form stack in fixed-width left panel
- tool rows with switch toggles
- inline "Add" text actions with plus icon
- top-center success toast
- floating composer card pinned to bottom of thread
- ghost toolbar buttons (Run, Clear, Logs)
- monospace ID caption under field
States it is designed for
- First-load skeleton for config fields
- Unsaved changes dot on assistant picker
- Saving / saved / save failed with retry caption
- Empty thread with hint text
- Run disabled with tooltip explaining why
- Streaming response with stop
- Run error (rate limit, invalid model) as inline red banner in thread with retry
- File upload progress, unsupported type error, size limit error
- Very long instructions (scroll within textarea, char counter warns near limit)
- Read-only state for viewers without edit rights
Who it is for
- Developers prototyping AI assistants
- Product teams tuning system prompts
- Solutions engineers demoing an AI API
Layout
- Top bar: page title, pill-shaped mode switcher, right-aligned docs link with external-arrow icon
- Icon-only left rail (48px) with section icons; account avatar pinned at bottom
- Config panel (~280px, bordered right): assistant picker, Name, Instructions textarea, Model select, Tools list with toggles, Files list
- Thread pane (fluid): small uppercase THREAD label, toolbar with Run / Clear / Logs top-right, empty message area
- Floating composer card near bottom of thread with textarea, "Add and run", "Add" and attach icon button; disclaimer line beneath
- Toast slides in top-center over the top bar on save
- Below 900px: config panel becomes a slide-over sheet opened from a "Configure" button; rail collapses into a bottom tab bar
Palette
quiet, technical, trustworthy, uncluttered. A workbench that stays out of the way so the prompt text is the hero.
- page and panel background
#ffffff - rail, composer chips, pill switcher
#f4f4f6 - dividers and card outlines (decorative)
#e5e6eb - input and select outlines
#8e8ea0 - primary text
#202123 - helper text, disclaimers, IDs
#6e6e80 - Add actions, links, focus ring
#0d8567 - success toast background
#0d8567 - text on toast and primary
#ffffff - disabled button label
#6e6e83
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text | 16.11:1 | 4.5:1 |
| Aa | muted helper text | 4.99:1 | 4.5:1 |
| Aa | toast label | 4.60:1 | 4.5:1 |
| Aa | accent Add link | 4.60:1 | 4.5:1 |
| input border | 3.22:1 | 3:1 | |
| focus ring | 4.60:1 | 3:1 | |
| Aa | muted text on rail surface | 4.55:1 | 4.5:1 |
| Aa | disabled label on muted chip | 4.53: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 scale
- Display
- Inter 600, 20px page title, -0.01em tracking
- Body
- Inter 400/500, 16px inputs and body, 14px labels (600), 13px helper captions; line-height 1.5
Similar to the observed neo-grotesk UI face. IDs and model names use JetBrains Mono 13px. The THREAD and TOOLS section labels are 12px uppercase with 0.06em tracking.
Spacing and imagery
Dense-but-calm: 4px base, 16px panel padding, 12px between field groups; radius 8px on inputs and buttons, 12px on the composer card, full pill on the mode switcher; one soft shadow (0 4px 16px rgba(0,0,0,.06)) on the composer and toast only.
No imagery. 16px outline icons in the rail and beside tool rows; small info-circle glyphs for tooltips.
Components
- Mode switcher pill (Assistants / Chat / Completions)
- Assistant picker with up/down chevron
- Name input with monospace ID caption and copy button
- Auto-growing Instructions textarea with expand-to-modal icon
- Model select
- Tool row: info icon, label, switch or "+ Add" action
- Files section with attach action and empty hint
- Thread toolbar: Run (disabled until messages exist), Clear, Logs toggle
- Message bubbles with role label
- Composer card with "Add and run", "Add" and attach buttons
- Success toast with dismiss
- Logs side drawer showing request/response JSON
Interactions
- Fields autosave 800ms after typing stops; toast confirms first creation and later a subtle "Saved" caption replaces it
- Cmd/Ctrl+Enter in composer = Add and run; Enter adds a newline
- Expand icon opens Instructions in a large modal editor with character count
- Switches animate 150ms; toggling a tool that needs files reveals the Files section
- Logs button toggles a right drawer that pushes the thread (300ms ease-out)
- Streaming assistant reply renders token-by-token with a stop button
- Toast auto-dismisses after 4s, pauses on hover/focus
Data
Assistant{id, org_id, name, instructions, model (enum), tools (code|retrieval|functions[]), created_by, updated_at}FunctionTool{id, assistant_id, name, json_schema, description}AssistantFile{id, assistant_id, filename, bytes, status (uploading|ready|failed)}Thread{id, assistant_id, created_by, created_at}Message{id, thread_id, role (user|assistant|tool), content, created_at}RunLog{id, thread_id, status (queued|running|completed|failed), request_json, response_json, latency_ms}
Guardrails
Experience
- Keep the config panel and thread visible together on desktop so edits and results sit side by side
- Autosave, but show a clear saved/failed status; never lose instruction text on navigation
- Disable Run only with an explanation (tooltip) rather than silently
- Show which model and tools were active on each run in the Logs drawer
- Warn before Clear wipes a thread that has more than a few messages
- Keep the disclaimer about org-wide visibility of test messages next to the composer
Accessibility
- Every field has a visible label bound with for/id; the ID caption is linked via aria-describedby
- Switches use role="switch" with aria-checked and the tool name as label
- Toast uses role="status" and is reachable; it does not steal focus
- Streaming replies announce completion (not every token) via a polite live region
- Icon-only rail buttons have tooltips and aria-labels
- Focus ring 2px accent with 2px offset on all controls
Security
- Call the model API from a server function; the API key never reaches the browser
- RLS: assistants, threads and messages scoped to org membership; viewers read-only
- Validate function JSON schema with zod before saving; cap instruction length
- Uploaded files: type allow-list, size cap, virus scan hook, private storage bucket
- Rate-limit runs per user and log each run for audit
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 **Sandbar**, a playground screen where developers configure an AI assistant and test it in the same view. The left panel holds the assistant's name, instructions, model, tools and files; the right side is a live test thread. Saving should feel instant and a success toast should confirm the first creation.
### Stack
React + TypeScript + Vite, Tailwind CSS, shadcn/ui on Radix, lucide-react icons. TanStack Query for assistant and thread data, react-hook-form + zod for the config form. Supabase for auth, Postgres and private file storage; a Supabase Edge Function proxies model calls and streams responses back.
### Pages & layout
1. **App shell**: 48px icon rail on the left (playground, assistants, threads, files, usage, settings; docs and account at the bottom); top bar with "Playground" title, a pill mode switcher and a right-aligned docs link.
2. **Config panel** (280px, right border): assistant picker with chevrons; Name input with a monospace ID caption and copy button; Instructions textarea with an expand icon; Model select; a TOOLS group of rows (Functions with "+ Add", Code runner switch, Retrieval switch); a FILES group with an attach action and an empty hint.
3. **Thread pane**: THREAD label left, Run / Clear / Logs buttons right; messages in the middle; a floating composer card anchored 24px above the bottom with "Add and run", "Add" and an attach icon, and a one-line disclaimer under it.
4. **Logs drawer**: slides in from the right, lists runs with status, latency and collapsible JSON.
5. Under 900px the config panel becomes a sheet opened from a "Configure" button, and the rail becomes a bottom tab bar.
### Design system
- Colors: `--bg: #ffffff` (page and panel background), `--surface-muted: #f4f4f6` (rail, composer chips, pill switcher), `--border: #e5e6eb` (dividers and card outlines (decorative)), `--input-border: #8e8ea0` (input and select outlines), `--fg: #202123` (primary text), `--muted: #6e6e80` (helper text, disclaimers, IDs), `--accent: #0d8567` (Add actions, links, focus ring), `--toast: #0d8567` (success toast background), `--on-accent: #ffffff` (text on toast and primary), `--disabled: #6e6e83` (disabled button label).
- Fonts: Inter (400/500/600) for UI, similar to the observed neo-grotesk; JetBrains Mono 13px for IDs and model names. Body 16px/1.5, labels 14px/600, helper 13px, uppercase section labels 12px with 0.06em tracking.
- Spacing: 4px base; 16px panel padding; 12px between field groups; 24px composer inset.
- Radius: 8px inputs and buttons, 12px composer and toast, full pill for the mode switcher.
- Shadows: `0 4px 16px rgba(0,0,0,.06)` on composer and toast only.
- Motion: 150ms switches, 200ms toast slide-down, 300ms drawer; all disabled under reduced motion.
### Components & interactions
AssistantPicker, ModeSwitcher, IdCaption (copy with "Copied" feedback), InstructionsField (auto-grow, expand modal, character counter), ModelSelect, ToolRow (switch or add action, info tooltip), FunctionDialog (name, description, JSON schema editor with validation), FileList (upload progress, remove), ThreadToolbar, MessageBubble (role label, copy), Composer (Cmd/Ctrl+Enter runs), StopButton, LogsDrawer, Toast. Autosave fires 800ms after typing; the first save shows the toast "Assistant created", later saves show a small "Saved" caption beside the picker.
### Data & state
Tables: `assistants(id, org_id, name, instructions, model, tools jsonb, created_by, updated_at)`, `assistant_files(id, assistant_id, path, bytes, status)`, `threads(id, assistant_id, created_by)`, `messages(id, thread_id, role, content, created_at)`, `run_logs(id, thread_id, status, request jsonb, response jsonb, latency_ms)`. Seed two mock assistants ("Copy Coach", "Support Triage") and a short sample thread. The form state is local until autosave. Streaming state lives in a reducer (idle, streaming, error). Handle these states: config skeleton, saving/saved/failed, empty thread, run disabled, streaming, run error with retry, upload errors, read-only viewer.
### Accessibility
Bind every label to its field; describe the ID caption and character counter with aria-describedby. Tool switches are `role="switch"` with the tool name as the accessible name. The toast is `role="status"` and never takes focus. Streaming output announces "Response complete" once. Rail icons get aria-labels and tooltips. Composer shortcuts are listed in a visible hint. Visible 2px focus rings in the accent colour.
Verified contrast: body text: #202123 on #ffffff = 16.11:1; muted helper text: #6e6e80 on #ffffff = 4.99:1; toast label: #ffffff on #0d8567 = 4.60:1; accent Add link: #0d8567 on #ffffff = 4.60:1; input border: #8e8ea0 on #ffffff = 3.22:1; focus ring: #0d8567 on #ffffff = 4.60:1; muted text on rail surface: #6e6e80 on #f4f4f6 = 4.55:1; disabled label on muted chip: #6e6e83 on #f4f4f6 = 4.53:1.
### Security
Model and API keys stay server-side in the Edge Function; the client sends only the assistant id and message. RLS on every table: org members can select; editors can insert/update; only the creator or an admin can delete assistants. Validate function schemas and instruction length with zod on the client and again server-side. Store files in a private bucket, allow only listed types, cap size, and use signed URLs. Rate-limit runs per user and write each run to `run_logs` for audit.
### Performance & SEO
Lazy-load the Logs drawer and JSON viewer. Debounce autosave and cancel stale requests. Virtualise long threads. Stream responses so the first tokens appear quickly. App routes are noindex.
### Guardrails
- Use invented assistant names and generic model labels; no real product names.
- Never show raw keys; mask IDs past the first few characters in screenshots.
- Keep the thread readable at 320px wide.
- Acceptance criteria: (1) editing any field autosaves and shows status; (2) first save shows the toast; (3) Run streams a reply and logs it; (4) Clear asks for confirmation; (5) all states above render with mock data; (6) keyboard-only users can configure and run.