SAV Design
One look for every Swiss Aerospace Ventures app: the Cruiser base-sera system as a shadcn registry. Tokens, 22 primitives on Base UI and the app patterns, copied into each app as source.
1. New app on the same preset (base-sera, neutral, Inter/Figtree, lucide):
npx shadcn@latest init -p b1HxL3L3Fg2. Register @sav in components.json:
npx shadcn@latest registry add @sav=https://design.sasv.ch/r/{name}.json3. Theme and fonts, once:
npx shadcn@latest add @sav/tokens4. Then whatever the page needs:
npx shadcn@latest add @sav/page-header @sav/data-panel @sav/stat-card- No new colours, no new typefaces. State colours alias existing tokens.
- Sharp corners: controls are
rounded-none. - Focusable controls ≥ 16 px on mobile (
text-base md:text-sm). - Uppercase tracking for buttons, labels and badges; Figtree for headings.
- Brand-neutral patterns: logo, app name and callbacks are props.
For agents: /llms.txt and /r/index.json.
Tokens · 4
- Tokens
@sav/tokensThe SAV theme: neutral oklch colour tokens for light and dark mode, radius 0.625rem, sidebar and chart tokens, and the font mappings (Inter → --font-sans, Figtree → --font-heading, Geist Mono → --font-geist-mono). Byte-equivalent to the Cruiser app's globals.css token block. - Font: Inter
@sav/font-interBody typeface. Google font Inter on the --font-sans variable (next/font/google in Next.js, @fontsource-variable/inter elsewhere). - Font: Figtree
@sav/font-figtreeHeading typeface. Google font Figtree on the --font-heading variable, used through the `font-heading` utility. - Font: Geist Mono
@sav/font-geist-monoCode and metrics typeface. Google font Geist Mono on the --font-geist-mono variable, mapped to --font-mono in @theme inline.
UI primitives · 23
- Alert Dialog
@sav/alert-dialogModal confirmation dialog that interrupts the user; sharp-cornered Sera variant on Base UI AlertDialog. - Avatar
@sav/avatarImage avatar with automatic initials fallback and three sizes; Base UI Avatar. - Badge
@sav/badgeUppercase tracking label in default, secondary, destructive and outline variants; renders as any element via `render`. - Breadcrumb
@sav/breadcrumbHierarchy trail with separators, ellipsis and link items. - Button
@sav/buttonUppercase tracking button in six variants and eight sizes on Base UI Button. Cruiser delta: `nativeButton` defaults to false when `render` is used so `render={<Link/>}` keeps anchor semantics. - Card
@sav/cardSharp-cornered content container with header, title, description, action, content and footer slots; `size="sm"` for stat tiles. - Chart
@sav/chartRecharts wrapper: ChartContainer with CSS-variable colour config, tooltip and legend styled with the design tokens. - Checkbox
@sav/checkboxSquare checkbox with an enlarged hit area; Base UI Checkbox. - Dialog
@sav/dialogModal dialog with overlay, header, footer and optional close button; Base UI Dialog. - Dropdown Menu
@sav/dropdown-menuMenu with items, checkbox and radio items, groups, labels, shortcuts and submenus; Base UI Menu. - Input
@sav/inputUnderlined text input (bottom border only). Mobile rule: text-base below md so iOS does not zoom on focus. - Label
@sav/labelUppercase tracking form label that relaxes to sentence case next to a checkbox, radio or switch. - Searchable Select
@sav/searchable-selectSingle-select typeahead on Base UI Combobox: case- and diacritic-insensitive filtering over label and keywords, keyboard support, 16px controls on mobile. Cruiser original (not in shadcn/ui). - Select
@sav/selectUnderlined select with groups, labels and scroll buttons; Base UI Select. Cruiser delta: trigger text is text-base below md (no iOS zoom). - Separator
@sav/separatorHorizontal or vertical divider; Base UI Separator. - Sheet
@sav/sheetSide panel sliding in from any edge, with header and footer; Base UI Dialog. - Sidebar
@sav/sidebarComposable sidebar shell: provider, rail, collapsible icon mode, mobile sheet, groups, menus, sub-menus and skeletons. - Skeleton
@sav/skeletonPulsing placeholder block for loading states. - Sonner (Toaster)
@sav/sonnerToast notifications via sonner, themed through next-themes and the popover tokens, with lucide status icons. - Table
@sav/tableData table primitives (header, body, footer, row, head, cell, caption) with a scrolling wrapper. - Textarea
@sav/textareaUnderlined auto-sizing textarea (field-sizing: content); text-base below md. - Tooltip
@sav/tooltipTooltip with provider, arrow and positioning; Base UI Tooltip. - useIsMobile
@sav/use-mobilematchMedia hook for the 768px breakpoint used by the sidebar.
App patterns · 11
- App Sidebar
@sav/app-sidebarAuthenticated app-shell navigation: brand block, labelled nav groups with active state from usePathname, user menu with links and sign-out callback; icon rail on desktop, drawer on mobile. Brand, groups, user and callbacks are props. - Brand Logo
@sav/brand-logoTheme-aware wordmark: a light-mode and a dark-mode asset passed as props, swapped with the dark variant. - Data Panel
@sav/data-panelSharp bordered container for tables and lists (bg-card + ring, horizontal scroll built in) with an optional DataPanelHeader title/action row. - Document Viewer
@sav/document-viewerDialog viewer for images and PDFs: zoom, drag-to-pan, multi-page navigation, download, pdf.js rendering with iframe fallback; InlineDocumentView for embedding without the dialog. - Empty State
@sav/empty-stateDashed-border centered empty/no-results panel with optional icon, description and action. - Notification Bell
@sav/notification-bellBell button with unread badge and a dropdown of recent notifications; optional polling through a fetchSummary callback, type labels and link targets as props. - Page Header
@sav/page-headerModule page header: heading-font title, optional description, right-aligned action slot, bottom separator. - PDF Pages
@sav/pdf-pagesRenders every page of a PDF to canvases with pdf.js, fit-to-width with zoom and device-pixel-ratio aware; lazy-loads the pdf.js module and worker. - Skeletons
@sav/skeletonsRoute-level loading skeletons: StatGridSkeleton, TableSkeleton, CardsGridSkeleton, PageHeaderSkeleton. - Stat Card
@sav/stat-cardKPI tile: uppercase label, large tabular value, optional icon, hint and monochrome delta arrow. - User Avatar
@sav/user-avatarAvatar from an optional image URL with first+last-name (or email) initials fallback; serializable props only.
Tokens
Surfaces
--backgroundoklch(1 0 0)oklch(0.145 0 0)--cardoklch(1 0 0)oklch(0.205 0 0)--popoveroklch(1 0 0)oklch(0.205 0 0)--mutedoklch(0.97 0 0)oklch(0.269 0 0)--accentoklch(0.97 0 0)oklch(0.269 0 0)--secondaryoklch(0.97 0 0)oklch(0.269 0 0)Text
--foregroundoklch(0.145 0 0)oklch(0.985 0 0)--card-foregroundoklch(0.145 0 0)oklch(0.985 0 0)--popover-foregroundoklch(0.145 0 0)oklch(0.985 0 0)--muted-foregroundoklch(0.556 0 0)oklch(0.708 0 0)--accent-foregroundoklch(0.205 0 0)oklch(0.985 0 0)--secondary-foregroundoklch(0.205 0 0)oklch(0.985 0 0)Primary & state
--primaryoklch(0.205 0 0)oklch(0.922 0 0)--primary-foregroundoklch(0.985 0 0)oklch(0.205 0 0)--destructiveoklch(0.577 0.245 27.325)oklch(0.704 0.191 22.216)--borderoklch(0.922 0 0)oklch(1 0 0 / 10%)--inputoklch(0.922 0 0)oklch(1 0 0 / 15%)--ringoklch(0.708 0 0)oklch(0.556 0 0)Charts
--chart-1oklch(0.87 0 0)oklch(0.87 0 0)--chart-2oklch(0.556 0 0)oklch(0.556 0 0)--chart-3oklch(0.439 0 0)oklch(0.439 0 0)--chart-4oklch(0.371 0 0)oklch(0.371 0 0)--chart-5oklch(0.269 0 0)oklch(0.269 0 0)Sidebar
--sidebaroklch(0.985 0 0)oklch(0.205 0 0)--sidebar-foregroundoklch(0.145 0 0)oklch(0.985 0 0)--sidebar-primaryoklch(0.205 0 0)oklch(0.488 0.243 264.376)--sidebar-primary-foregroundoklch(0.985 0 0)oklch(0.985 0 0)--sidebar-accentoklch(0.97 0 0)oklch(0.269 0 0)--sidebar-accent-foregroundoklch(0.205 0 0)oklch(0.985 0 0)--sidebar-borderoklch(0.922 0 0)oklch(1 0 0 / 10%)--sidebar-ringoklch(0.708 0 0)oklch(0.556 0 0)Values: first line light, second line dark. --radius is 0.625rem; the Sera style sets rounded-none on controls, so the radius scale only reaches cards and toasts.
Type scale
Headings · Figtree (--font-heading)
text-4xlSwiss Aerospace Venturestext-3xlSwiss Aerospace Venturestext-2xl · page titleSwiss Aerospace Venturestext-xlSwiss Aerospace Venturestext-lgSwiss Aerospace Venturestext-sm · panel titleSwiss Aerospace VenturesBody · Inter (--font-sans)
text-baseThe quick brown fox jumps over the lazy dog. Controls use 16 px on mobile so iOS does not zoom on focus.
text-smDefault reading size on desktop: tables, forms, descriptions and menu items.
text-xs uppercaseButtons, labels and badges
text-xs mutedHints, timestamps and secondary metadata.
Mono · Geist Mono (--font-geist-mono → --font-mono)
CHF 12'480.00 · 2026-11-07T16:45:00Z · npx shadcn@latest add @sav/tokens