Template
Ruskel
After an admin authorises a new data source in an AI workspace, a side sheet confirms the sync has started, explains where the synced data will appear and how to share it (company-wide or restricted spaces), and offers a short explainer video. It turns a long background job into a moment of orientation.
Data-sync-in-progress side sheet with explainer video · App screen: integrations · 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 sheet title
- InterBody: Inter 400, 16px, line-height 1.55
Patterns
- right side sheet over dimmed app
- sparkle icon plus status title
- highlighted callout box with bullet list
- embedded explainer video with captions
- single acknowledge button bottom-right
- admin sidebar with grouped spaces
- trial usage meter in sidebar footer
States it is designed for
- syncing: badge with spinner and item count
- sync finished: success toast and badge becomes 'Synced'
- sync failed: row shows error text and Retry; sheet copy switches to error variant
- partial sync: count of skipped items with a details link
- video failed to load: poster with 'Watch on docs page' link
- empty spaces list: 'New' prompt in the sidebar section
Who it is for
- workspace admins of an AI assistant platform
- IT or ops leads connecting company data
Layout
- top of sidebar: three tabs (Chat, Spaces, Admin) with icons
- sidebar sections: Administration (Connections, Tools, Triggers), Open spaces with New action, Restricted spaces with New action; footer with trial message meter and workspace switcher and Help
- main (dimmed under scrim): Connections admin page with description and a table of sources (name, used by)
- right side sheet (~40% width, min 420px): icon, title, yellow callout, video player, documentation line, 'OK' button bottom-right
- below 768px the sheet becomes a full-screen bottom sheet and the video spans full width
Palette
Reassuring and instructional; a warm yellow callout says 'this is normal, here is what happens next'.
- bg
#ffffff - canvas
#f6f7f9 - scrim
#5b6475 - text
#161b26 - muted
#5e6675 - callout
#fff6c7 - callout-text
#5c4a00 - link
#1a73d9 - button
#1e2533 - meter
#2e7df6
Every checked pair, measured again
| Sample | Where | Ratio | Needs |
|---|---|---|---|
| Aa | body text | 17.23:1 | 4.5:1 |
| Aa | muted text on sidebar | 5.39:1 | 4.5:1 |
| Aa | callout text | 7.91:1 | 4.5:1 |
| Aa | link text | 4.67:1 | 4.5:1 |
| Aa | OK button label | 15.35:1 | 4.5:1 |
| usage meter fill vs track | 3.15:1 | 3:1 | |
| focus ring | 4.67: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
- Inter 600, 20px sheet title
- Body
- Inter 400, 16px, line-height 1.55
Sidebar group labels 13px 600 in muted text; bold spans inside the callout highlight the two access options.
Spacing and imagery
Density: Medium density. Grid: 8px base; sheet padding 24px; 16px between blocks. Container: sheet width 40vw clamped 420-560px. Radius: 10px callout and video, 8px buttons. Shadows: Sheet casts a large left shadow 0 0 40px rgba(0,0,0,0.18).
A small sparkle glyph as the sheet icon; a 16:9 explainer video poster showing a generic UI tree; no stock photos.
Components
- AppSidebar with tabs and grouped sections
- UsageMeter
- ConnectionsTable
- SideSheet
- Callout
- VideoPlayer with captions toggle
- SyncStatusBadge
- Toast
Interactions
- Sheet opens automatically after OAuth success and can be closed with OK, Esc or clicking the scrim
- Video has play, captions, volume, settings and fullscreen controls; captions default on when OS prefers them
- Documentation link opens in a new tab with an external-link icon
- The source row in the table shows a 'Syncing' badge with progress that updates via polling every 10s
- When sync finishes a toast offers 'Add to a space'
Data
DataSource{id, workspace_id, provider (files|docs|chat|warehouse), status (syncing|synced|failed|paused), items_synced, items_total, last_synced_at}Space{id, workspace_id, name, visibility (open|restricted)}SpaceSource{space_id, source_id}SyncJob{id, source_id, started_at, finished_at, error}
Guardrails
Experience
- Tell users sync runs in the background and they can close the sheet
- State exactly where the data will appear and the two ways to share it
- Never autoplay the video
- Keep one primary action (OK) in the sheet
- Show sync progress on the table row after the sheet closes
Accessibility
- Side sheet is a Radix Dialog with aria-labelledby on the title; focus starts on the title
- Video has captions and a transcript link
- Progress uses role=progressbar with aria-valuenow and text count
- Bold text in the callout is not the only signal; each option is a list item
- Scrim click-to-close is mirrored by Esc and the OK button
Security
- Only workspace admins can create data sources (RLS on data_sources: insert/update for admin role)
- OAuth tokens for sources are stored encrypted server-side and never sent to the client
- Synced items inherit space visibility; restricted spaces check membership in RLS
- Audit-log each source connection and each space assignment
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 **Ruskel**, the moment right after an admin connects a company data source to an AI workspace. A side sheet explains that syncing has started, where the data will land and how to share it, with a short captioned video. Build the admin connections page behind a scrim, the sidebar shell and the sheet, with mock sync progress.
### Stack
React 18 + TypeScript + Vite, Tailwind CSS, shadcn/ui on Radix primitives and lucide-react icons. TanStack Query for server state, react-hook-form + zod for every form, date-fns for relative times. Supabase for Auth, Postgres with row-level security and Edge Functions for anything that needs a secret. Run syncs in a background worker; the client polls or subscribes through a realtime channel.
### Pages & layout
1. **Sidebar**: tabs Chat / Spaces / Admin; Administration group; Open spaces and Restricted spaces groups each with a '+ New' action; footer with a trial usage meter (e.g. 3 of 100 messages) and a workspace switcher.
2. **Connections admin page**: title with icon, two-line description with a help link, table with Name (sortable) and Used by columns.
3. **Sync side sheet**: sparkle icon, title 'Syncing your data…', yellow callout with a sentence and two bullets (open space vs restricted space), 16:9 video with controls, 'See the docs' line, OK button bottom-right.
Responsive: sheet becomes full-screen below 768px.
### Design system
- Colors: `--bg: #ffffff` (sheet surface), `--canvas: #f6f7f9` (sidebar and page), `--scrim: #5b6475` (overlay at 55% opacity), `--text: #161b26` (primary text), `--muted: #5e6675` (secondary text), `--callout: #fff6c7` (callout fill), `--callout-text: #5c4a00` (callout body), `--link: #1a73d9` (links), `--button: #1e2533` (OK button fill), `--meter: #2e7df6` (usage meter fill).
- Fonts: Inter 600, 20px sheet title for headings; Inter 400, 16px, line-height 1.55 for body. Sidebar group labels 13px 600 in muted text; bold spans inside the callout highlight the two access options.
- Spacing: Medium density. 8px base; sheet padding 24px; 16px between blocks. Container: sheet width 40vw clamped 420-560px.
- Radius: 10px callout and video, 8px buttons.
- Shadows: Sheet casts a large left shadow 0 0 40px rgba(0,0,0,0.18).
- Motion: Sheet slides in from the right over 220ms ease-out with scrim fade; video never autoplays; reduced motion swaps slide for fade.
### Components & interactions
The Callout is a rounded yellow box with dark olive text, a lead sentence and a two-item list whose key words are bold. The VideoPlayer is a rounded card with a centred play button and a control bar; add a captions toggle.
- Sheet opens automatically after OAuth success and can be closed with OK, Esc or clicking the scrim
- Video has play, captions, volume, settings and fullscreen controls; captions default on when OS prefers them
- Documentation link opens in a new tab with an external-link icon
- The source row in the table shows a 'Syncing' badge with progress that updates via polling every 10s
- When sync finishes a toast offers 'Add to a space'
### Data & state
Mock one source moving from 0 to 1,240 items over 60 seconds using a fake timer, then flip to synced. Server state via TanStack Query with a 10s refetch interval while status is syncing; stop polling when done.
Entities: `DataSource{id, workspace_id, provider (files|docs|chat|warehouse), status (syncing|synced|failed|paused), items_synced, items_total, last_synced_at}`; `Space{id, workspace_id, name, visibility (open|restricted)}`; `SpaceSource{space_id, source_id}`; `SyncJob{id, source_id, started_at, finished_at, error}`.
States to build and show in a dev-only state switcher:
- syncing: badge with spinner and item count
- sync finished: success toast and badge becomes 'Synced'
- sync failed: row shows error text and Retry; sheet copy switches to error variant
- partial sync: count of skipped items with a details link
- video failed to load: poster with 'Watch on docs page' link
- empty spaces list: 'New' prompt in the sidebar section
### Accessibility
- Side sheet is a Radix Dialog with aria-labelledby on the title; focus starts on the title
- Video has captions and a transcript link
- Progress uses role=progressbar with aria-valuenow and text count
- Bold text in the callout is not the only signal; each option is a list item
- Scrim click-to-close is mirrored by Esc and the OK button
Verified contrast: body text: #161b26 on #ffffff = 17.23:1; muted text on sidebar: #5e6675 on #f6f7f9 = 5.39:1; callout text: #5c4a00 on #fff6c7 = 7.91:1; link text: #1a73d9 on #ffffff = 4.67:1; OK button label: #ffffff on #1e2533 = 15.35:1; usage meter fill vs track: #2e7df6 on #e3e7ee = 3.15:1; focus ring: #1a73d9 on #ffffff = 4.67:1.
### Security
- Only workspace admins can create data sources (RLS on data_sources: insert/update for admin role)
- OAuth tokens for sources are stored encrypted server-side and never sent to the client
- Synced items inherit space visibility; restricted spaces check membership in RLS
- Audit-log each source connection and each space assignment
RLS detail: `data_sources` select for workspace members, write for admins; `spaces` select for members of open spaces or members listed in `space_members` for restricted ones; `sync_jobs` insert only by the service role.
### Performance & SEO
Load the video lazily (poster first, player on click). Keep the sheet in a separate chunk. Private admin route: noindex.
### Guardrails
- Tell users sync runs in the background and they can close the sheet
- State exactly where the data will appear and the two ways to share it
- Never autoplay the video
- Keep one primary action (OK) in the sheet
- Show sync progress on the table row after the sheet closes
- Write fresh, generic copy and invented sample data; no real brands, logos, product names or people.
- Keep components small and typed (no `any`); surface every error visibly with a way to recover.
Acceptance criteria:
- Sheet appears after connecting and closes via OK, Esc and scrim
- Row badge progresses and flips to Synced with a toast
- Failure shows Retry on the row
- Video never autoplays and has captions
- Non-admins cannot open the connections page