A multi-platform design system based on the Nordic design principles of Hygge (warmth) and Lagom (balance).
Candi provides a unified system for colors using the OKLCH color space, synchronized across Web, Flutter, VS Code, Vim, KDE, GNOME, and Obsidian.
View Documentation Website - Interactive color explorer, component playground, and comprehensive guides.
| Platform | Support | Integration |
|---|---|---|
| Web | Full | Tailwind CSS Plugin & CSS Variables |
| Flutter | Full | Type-safe CandiColors with OKLCH metadata |
| VS Code | Full | Light & Dark themes with unified syntax highlighting |
| Vim | Full | Standalone .vim colorschemes (GUI & Terminal) |
| KDE Plasma | Full | Color schemes for KDE 4, 5 & 6 |
| GNOME | Full | GTK3 & GTK4 themes for X11 and Wayland |
| Obsidian | Full | Light & Dark themes with 60+ CSS variables |
| Showcase App | Full | Interactive Flutter gallery & playground |
The Single Source of Truth (SSOT) in Candi is a unified structure composed of two parts with disparate responsibilities: the Derivation Engine (rules and anchors) and the Palette Assembly (neutrals and composition). This model ensures that the SSOT remains robust while following the Single Responsibility Principle (SRP) for both automated generation and manual tuning.
Derivation Engine (scripts/gen-oklch-primitives.js)
│ (Rules & Anchors)
▼
Palette Assembly (src/data/colors.js)
│ (Neutrals & Composition)
▼
Synchronization (scripts/sync-colors.js)
│
├── src/css/base.css (CSS Variables)
├── src/v4/theme.css (Tailwind v4 @theme)
└── dist/colors.json (Data export)
Platform Builds (Consuming Assembly & Engine):
├── build-flutter.js → flutter/lib/candi_colors.dart
├── build-vscode.js → vscode/themes/*.json
├── build-vim.js → vim/colors/*.vim
├── build-kde.js → kde/v4,v5/*.colors
├── build-gnome.js → gnome/gtk-*/*.css
├── build-obsidian.js → obsidian/theme.css
└── build-showcase.js → showcase_flutter/
Candi uses OKLCH as its primary color space instead of Hex codes:
- Perceptual Uniformity: Consistent contrast and brightness across the palette
- Synchronized Themes: Updates to
src/data/colors.jspropagate to all platforms vianpm run build:all - Shared Logic: Centralized conversion in
scripts/color-conv.jsensures color accuracy - Automated Accessibility: Integrated WCAG 2.1 contrast ratio validation
Learn more about OKLCH color conversion
candi/
├── ARCHITECTURE.md # System architecture and SSOT design
├── Knowledge.md # Lessons learned and development notes
├── src/ # Source files for npm package
│ ├── css/ # CSS files (base, components, utilities)
│ ├── data/ # Source of truth (colors.js)
│ ├── v4/ # Tailwind v4 @theme
│ ├── index.js # Main entry point
│ ├── plugin.js # Tailwind v3 plugin
│ ├── theme.js # Tailwind v3 theme extension
│ └── types.d.ts # TypeScript type definitions
├── scripts/ # Build, test, and utility scripts
│ ├── build.js # Main npm package build
│ ├── build-*.js # Platform-specific builds
│ ├── test-*.js # Platform-specific tests
│ ├── sync-colors.js # Color synchronization
│ ├── color-conv.js # Color conversion utilities
│ ├── gen-oklch-primitives.js # Derivation engine
│ └── package-artifacts.js # Release packaging script
├── schemas/ # JSON Schemas for token validation
├── dist/ # Built output (git-ignored)
├── docs/ # Documentation guides
├── website/ # Documentation site (Vite + React)
├── flutter/ # Flutter package
├── vscode/ # VS Code extension
├── vim/ # Vim colorschemes
├── kde/ # KDE Plasma color schemes
├── gnome/ # GTK3/GTK4 themes
├── obsidian/ # Obsidian theme
└── showcase_flutter/ # Flutter showcase application
| Command | Description |
|---|---|
npm run build |
Build npm package (CSS, JS, TypeScript declarations) |
npm run build:all |
Build all platforms (Web, Flutter, VS Code, Vim, KDE, GNOME, Obsidian) |
npm run build:flutter |
Build Flutter package only |
npm run build:vscode |
Build VS Code extension only |
npm run build:vim |
Build Vim colorschemes only |
npm run build:kde |
Build KDE color schemes only |
npm run build:gnome |
Build GNOME/GTK themes only |
npm run build:obsidian |
Build Obsidian theme only |
npm run build:showcase |
Build Flutter showcase app only |
| Command | Description |
|---|---|
npm test |
Run all tests |
npm run test:color |
Test color definitions |
npm run test:colors |
Test color conversions |
npm run test:flutter |
Test Flutter package |
npm run test:vscode |
Test VS Code extension |
npm run test:vim |
Test Vim colorschemes |
npm run test:kde |
Test KDE color schemes |
npm run test:gnome |
Test GNOME themes |
npm run test:obsidian |
Test Obsidian theme |
npm run test:showcase |
Test Flutter showcase app |
| Command | Description |
|---|---|
npm run artifact |
Package all platforms into zip archives |
npm run vscode:package |
Generate .vsix VS Code extension |
./scripts/package-bump.sh <version> |
Bump version across all packages |
Download ready-to-use artifacts from GitHub releases (recommended for most users).
npm install @wtasnorg/candiTailwind v4 (Recommended):
/* In your CSS */
@import "tailwindcss";
@import "@wtasnorg/candi/v4";Tailwind v3:
// tailwind.config.js
const { theme, plugin } = require('@wtasnorg/candi');
module.exports = {
theme: { extend: theme },
plugins: [plugin],
};Full Web Setup Guide | Use Without Tailwind
| Platform | Guide |
|---|---|
| Flutter | Flutter Integration Guide |
| VS Code | VS Code Theme Guide |
| Vim | Vim Theme Guide |
| KDE Plasma | KDE Theme Guide |
| GNOME | GNOME Theme Guide |
| Obsidian | Obsidian Theme Guide |
| Token | Light | Dark | Usage |
|---|---|---|---|
bg |
Warm white | Warm dark (Hygge) | Page background |
surface |
Soft cream | Warm dark surface | Cards, sections |
elevated |
Pure white | Warm elevated dark | Modals, popups |
text |
Warm charcoal | Off-white | Primary text |
text-subtle |
Medium gray | Light gray | Secondary text |
text-muted |
Light gray | Muted gray | Tertiary text |
accent |
Steel blue | Lighter steel | Primary actions |
secondary |
Terracotta | Lighter terracotta | Secondary actions |
success |
Forest green | Lighter green | Success states |
warning |
Amber | Lighter amber | Warning states |
error |
Coral red | Lighter coral | Error states |
Candi prioritizes accessibility through automated validation:
- WCAG Compliance: Contrast ratios are validated programmatically during the color extraction pipeline.
- Primary Text: Targets 4.5:1 (WCAG AA) for standard text.
- UI Elements: Accents and state indicators target 3.0:1 (WCAG Graphical Objects).
- Node.js 24+
- npm
- Flutter SDK (for Flutter package development)
# Clone the repository
git clone https://github.com/wtasg/candi.git
cd candi
# Install dependencies
npm install
# Build all platforms
npm run build:allThe documentation site in website/ consumes the built theme from dist/:
cd website
npm install
npm run dev- Edit authoritative anchors in
src/data/colors.js. - Run
npm run build:allto regenerate platform themes via the derivation engine. - Run
npm testto validate system-wide harmony and contrast.
- Knowledge Base - Lessons learned and development gotchas
- Color Conversion - OKLCH to RGB conversion pipeline
MIT