Design System

Visual reference for the Vendel design language. Use this as the single source of truth for colors, typography, components, and patterns across the homepage and dashboard.

Colors

Mint-tinted palette built around the accent color #2dd4a8. All grays carry a subtle green tint for cohesion.

Accent

#2dd4a8 accent
#1fa888 accent-hover
#6ee7c2 accent-light

Background & Text

#edf5f1 bg
#181c1b bg-dark / text
#6b6b6b text-muted
#edf5f1 text-light

Dark Theme

#0c0f0e dark-bg
#181c1b dark-surface
#222826 dark-surface-alt
#2a2e2d dark-secondary
#3a3e3d dark-border
#f7faf9 dark-text

Neutral Scale (Mint-tinted Grays)

50#f7faf9
100#edf5f1
200#e0e8e4
300#ccd4d0
400#a0a8a4
500#707874
600#545c58
700#383e3c
800#222826
900#181c1b
950#0c0f0e

Code Syntax Highlighting

#222826code-bg
#edf5f1text / function
#2dd4a8keyword
#6ee7c2string
#ccd4d0variable
#707874comment
#a0a8a4punctuation

Typography

Three font families — a clean sans-serif for body text, a classic serif for headings, and a monospace for code.

Sans — Body, UI, Navigation

Inter

font-family: "Inter", ui-sans-serif, system-ui, sans-serif

Regular 400 Medium 500 Semibold 600
Serif — Headings, Card Titles

Libre Baskerville

font-family: "Libre Baskerville", ui-serif, Georgia, serif

Regular 400 Bold 700
Mono — Code, Tokens, Data

JetBrains Mono

font-family: "JetBrains Mono", ui-monospace, monospace

Regular 400 Medium 500

Heading Scale

5xl

Heading One

4xl

Heading Two

3xl

Heading Three

2xl

Heading Four

xl
Heading Five
lg
Heading Six

Body Text

Large body text for introductions and hero sections. Uses Inter at 18px with relaxed line-height for comfortable reading.

Default body text for general content. Inter at 16px with normal line-height. Used throughout cards, descriptions, and documentation paragraphs.

Small text for captions, metadata, and secondary information. Inter at 14px in a muted color.

Tiny monospace for labels, timestamps, and technical metadata. JetBrains Mono at 12px.

Buttons

Three button variants for different levels of emphasis. All support an optional trailing icon.

Primary — Main actions

.btn .btn-primary

Secondary — Alternative actions

.btn .btn-secondary

Link — Inline / subtle actions

.btn .btn-link

Pills

Inline status indicators and labels. Rounded-full shape with tinted backgrounds for clear visual hierarchy.

Accent — Positive status, active states

Set via env Active Configured

.pill .pill-accent

Light: neutral-700 text on brand/15 bg (7.5:1 contrast). Dark: brand text on brand/20 bg (5.2:1).

Neutral — Informational, metadata

Default v2.1.0 Monthly

.pill .pill-neutral

Destructive — Errors, warnings

Failed Expired Overdue

.pill .pill-destructive

Cards

Container components for grouping related content. Three variants for different visual weight.

Default Card

Standard card with a subtle border. Used for feature lists and general content grouping.

  • Standard border
  • White background
  • Rounded corners

.card .card-default

Muted Card

Subtle card with a tinted background. Used for secondary information and asides.

  • Neutral-50 background
  • Subtle border
  • Low visual weight

.card .card-muted

Code Blocks

Syntax-highlighted code using the custom vendel-dark Shiki theme. Supports an optional filename header.

JavaScript — with filename

send-sms.js
const response = await fetch("/api/sms/send", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Key": "your-api-key"
  },
  body: JSON.stringify({
    to: "+1234567890",
    message: "Hello from Vendel!"
  })
});

const data = await response.json();
console.log(data.id); // "msg_abc123"

JSON — webhook payload

webhook-payload.json
{
  "event": "sms.delivered",
  "data": {
    "id": "msg_abc123",
    "to": "+1234567890",
    "status": "delivered",
    "device": "pixel-7a",
    "delivered_at": "2026-02-22T14:30:00Z"
  }
}

Bash — no filename

curl -X POST https://your-server.com/api/sms/send \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{"to": "+1234567890", "message": "Hello!"}'

YAML — Docker Compose

docker-compose.yml
services:
  app:
    build: .
    ports:
      - "8090:8090"
    volumes:
      - vendel-data:/app/pb_data
    environment:
      - ENVIRONMENT=production

Inline Code

Use the X-API-Key header to authenticate requests. Send messages via POST /api/sms/send with a JSON body. The device_id field is optional.

Alerts

Contextual banners for informational and warning messages within documentation.

Info: PocketBase serves the frontend SPA, API, and admin dashboard from a single binary on port 8090.
Warning: Make sure to set WEBHOOK_ENCRYPTION_KEY in production. Without it, webhook secrets are stored in plaintext.

.alert .alert-info

.alert .alert-warning

Patterns & Decorations

Visual elements used for texture and emphasis across the site.

Dot Pattern

.dot-pattern

Accent Dot

.accent-dot
12px circle

Accent Circle

.accent-circle
Scalable

Dark Section

Dark background sections

Used for high-contrast feature sections. Background neutral-900 with white text and neutral-400 for muted content.

Accent bullets Muted bullets

Design Tokens

CSS custom properties defined in global.css via Tailwind v4's @theme block. Copy these into any project to match the Vendel look.

global.css — @theme
# Typography
--font-sans:   "Inter", ui-sans-serif, system-ui, sans-serif
--font-serif:  "Libre Baskerville", ui-serif, Georgia, serif
--font-mono:   "JetBrains Mono", ui-monospace, monospace

# Accent
--color-accent:        #2dd4a8
--color-accent-hover:  #1fa888

# Background & Text
--color-bg:            #edf5f1
--color-bg-dark:       #181c1b
--color-text:          #181c1b
--color-text-muted:    #6b6b6b
--color-text-light:    #edf5f1

# Neutral Scale (mint-tinted)
--color-neutral-50:    #f7faf9
--color-neutral-100:   #edf5f1
--color-neutral-200:   #e0e8e4
--color-neutral-300:   #ccd4d0
--color-neutral-400:   #a0a8a4
--color-neutral-500:   #707874
--color-neutral-600:   #545c58
--color-neutral-700:   #383e3c
--color-neutral-800:   #222826
--color-neutral-900:   #181c1b
--color-neutral-950:   #0c0f0e

# Code Syntax
--color-code-bg:          #222826
--color-code-text:        #edf5f1
--color-code-comment:     #707874
--color-code-string:      #6ee7c2
--color-code-keyword:     #2dd4a8
--color-code-function:    #edf5f1
--color-code-variable:    #ccd4d0
--color-code-punctuation: #a0a8a4

Google Fonts Import

index.html or Layout.astro
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Libre+Baskerville:wght@400;700&display=swap" rel="stylesheet" />

Dashboard (shadcn/ui) Token Mapping

The React dashboard maps the same palette to shadcn semantic variables. This is the bridge between the homepage tokens and the dashboard's component library.

frontend/src/index.css — :root
# shadcn semantic colors → Vendel palette
--background:             #edf5f1   # neutral-100
--foreground:             #181c1b   # neutral-900
--card:                   #edf5f1   # neutral-100
--primary:                #181c1b   # neutral-900  (dark buttons)
--primary-foreground:     #ffffff
--secondary:              #e0e8e4   # neutral-200
--secondary-foreground:   #545c58   # neutral-600
--muted:                  #e0e8e4   # neutral-200
--muted-foreground:       #707874   # neutral-500
--accent:                 #e0e8e4   # neutral-200  (hover states)
--accent-foreground:      #181c1b   # neutral-900
--border:                 #ccd4d0   # neutral-300
--input:                  #ccd4d0   # neutral-300
--ring:                   #181c1b   # neutral-900
--destructive:            #dc2626   # red-600

# Chart colors use the mint accent
--chart-1:  #2dd4a8   # accent
--chart-2:  #6ee7c2   # accent-light
--chart-3:  #707874   # neutral-500
--chart-4:  #ccd4d0   # neutral-300
--chart-5:  #1fa888   # accent-hover