{"id":49790744,"url":"https://github.com/low-orbit-studio/visor","last_synced_at":"2026-06-12T05:01:25.107Z","repository":{"id":345613946,"uuid":"1186603046","full_name":"low-orbit-studio/visor","owner":"low-orbit-studio","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-11T22:46:23.000Z","size":33552,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-12T00:12:17.602Z","etag":null,"topics":["component-library","css-modules","design-system","nextjs","oklch","react","shadcn-style","theming","visor"],"latest_commit_sha":null,"homepage":"https://visor-docs.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/low-orbit-studio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":"GOVERNANCE.md","roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":"MAINTAINERS.md","copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"custom":[]}},"created_at":"2026-03-19T19:56:29.000Z","updated_at":"2026-06-11T22:39:57.000Z","dependencies_parsed_at":null,"dependency_job_id":"7da2ccdc-28a3-4be7-9198-6af6f00ecebd","html_url":"https://github.com/low-orbit-studio/visor","commit_stats":null,"previous_names":["low-orbit-studio/visor"],"tags_count":47,"template":false,"template_full_name":null,"purl":"pkg:github/low-orbit-studio/visor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/low-orbit-studio%2Fvisor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/low-orbit-studio%2Fvisor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/low-orbit-studio%2Fvisor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/low-orbit-studio%2Fvisor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/low-orbit-studio","download_url":"https://codeload.github.com/low-orbit-studio/visor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/low-orbit-studio%2Fvisor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34229624,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["component-library","css-modules","design-system","nextjs","oklch","react","shadcn-style","theming","visor"],"created_at":"2026-05-12T04:00:36.838Z","updated_at":"2026-06-12T05:01:25.027Z","avatar_url":"https://github.com/low-orbit-studio.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/visor-logo-dark.png\" alt=\"Visor — One component system. Total Control. By Low Orbit Studio\" width=\"480\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@loworbitstudio/visor-core\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@loworbitstudio/visor-core?label=visor-core\" alt=\"visor-core version\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@loworbitstudio/visor\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@loworbitstudio/visor?label=visor+cli\" alt=\"CLI version\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@loworbitstudio/visor-theme-engine\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/@loworbitstudio/visor-theme-engine?label=theme-engine\" alt=\"theme-engine version\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/low-orbit-studio/visor/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/low-orbit-studio/visor/ci.yml?branch=main\u0026label=CI\" alt=\"CI\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/low-orbit-studio/visor/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/low-orbit-studio/visor\" alt=\"License\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@loworbitstudio/visor-core\"\u003e\u003cimg src=\"https://img.shields.io/npm/dm/@loworbitstudio/visor-core?label=downloads\" alt=\"npm downloads\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://bundlephobia.com/package/@loworbitstudio/visor-core\"\u003e\u003cimg src=\"https://img.shields.io/bundlephobia/minzip/@loworbitstudio/visor-core?label=visor-core\" alt=\"bundle size\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://visor.loworbit.studio\"\u003eDocumentation\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## What is Visor?\n\nVisor is a theming-first React component library built by [Low Orbit Studio](https://loworbit.studio). It uses a two-layer distribution model that gives you full control over your components while keeping design consistency effortless:\n\n**Layer 1 — Components (copy-and-own).** Run `npx visor add button` and the source files are copied directly into your project. You own them. Edit them freely. No runtime dependency on Visor.\n\n**Layer 2 — Tokens (`@loworbitstudio/visor-core`).** The only npm package. It provides all the CSS custom properties that Visor components reference. Update the package and design changes cascade to every component automatically — without touching a single component file.\n\nThis model is inspired by shadcn/ui's copy-and-own approach, combined with a shared token layer that keeps multi-project consistency without locking you in.\n\n---\n\n## Quick Start\n\n### One command. Runnable Next.js app. Borealis-native.\n\nIn an empty directory, run:\n\n```sh\nnpx @loworbitstudio/visor init --template nextjs\n```\n\nThat single command scaffolds a complete, runnable Next.js App Router project pre-wired with Visor:\n\n- `package.json` with `next`, `react`, TypeScript, and `@loworbitstudio/visor-core` + `@loworbitstudio/visor-theme-engine` already installed.\n- `app/layout.tsx` with the FOWT (Flash of Wrong Theme) prevention script inline in `\u003chead\u003e` and `globals.css` imported.\n- `app/globals.css` generated from `.visor.yaml` via the Visor Next.js adapter.\n- `app/page.tsx`, `tsconfig.json`, `next.config.ts`, `.gitignore` — the full create-next-app baseline.\n- `.lo/borealis.json` stamp recording the Visor version that initialized the project.\n\nThen start the dev server:\n\n```sh\ncd my-app \u0026\u0026 npm run dev\n```\n\nAdd your first component:\n\n```sh\nnpx visor add button\n```\n\nThat's it. The component source lands in your project and you own it. No FOWT flash, no missing config, no second setup step.\n\n\u003e **Heads up:** `visor init --template nextjs` only scaffolds into empty directories — it refuses if `package.json` already exists so it never destructively overwrites in-flight work. For an existing app, use the manual setup below.\n\n### Manual setup (non-Next.js or retrofit)\n\nFor non-Next.js projects, or to retrofit Visor into an existing app:\n\n**1. Initialize Visor**\n\n```sh\nnpx @loworbitstudio/visor init\n```\n\nThis creates a `visor.json` in your project root with default path mappings:\n\n```json\n{\n  \"paths\": {\n    \"components\": \"components/ui\",\n    \"hooks\": \"hooks\",\n    \"lib\": \"lib\"\n  }\n}\n```\n\n**2. Import tokens into your global CSS**\n\n```css\n/* app/globals.css or src/index.css */\n@import \"@loworbitstudio/visor-core\";\n```\n\n**3. Add your first component**\n\n```sh\nnpx visor add button\n```\n\n---\n\n## Adding Components\n\nAdd components one at a time or in bulk:\n\n```sh\nnpx visor add input\nnpx visor add card\nnpx visor add button input label card\n```\n\n### Available Components\n\nThe registry ships 88+ UI components across 6 categories, plus admin compounds, blocks, and hooks.\n\n**Form (24)**\n`button` · `calendar` · `checkbox` · `combobox` · `date-picker` · `field` · `fieldset` · `file-upload` · `form` · `input` · `label` · `number-input` · `otp-input` · `password-input` · `phone-input` · `radio-group` · `search-input` · `select` · `slider` · `slider-control` · `switch` · `tag-input` · `textarea` · `toggle-group`\n\n**Data Display (12)**\n`accordion` · `avatar` · `carousel` · `code-block` · `collapsible` · `heading` · `image` · `progress` · `separator` · `skeleton` · `text` · `timeline`\n\n**Navigation (5)**\n`breadcrumb` · `command` · `navbar` · `pagination` · `stepper`\n\n**Overlay (7)**\n`context-menu` · `dialog` · `fullscreen-overlay` · `hover-card` · `lightbox` · `menubar` · `popover`\n\n**Feedback (6)**\n`alert` · `banner` · `chart` · `table` · `toast` · `tooltip`\n\n**Layout (9)**\n`badge` · `box` · `card` · `container` · `grid` · `inline` · `sheet` · `sidebar` · `stack`\n\nThe five primitives `box`, `container`, `grid`, `inline`, and `stack` are token-typed layout building blocks: all spacing, surface, and radius props accept only Visor token names — off-system values are TypeScript errors. Pair them with `Card`, `Sheet`, and `Sidebar` for full-page chrome.\n\nAdd an entire category at once:\n\n```sh\nnpx visor add --category form      # Add all form components\nnpx visor add --category overlay   # Add all overlay components\n```\n\n### Admin Components\n\n11 compound components for data-heavy admin UIs. Add with `--category admin`:\n\n```sh\nnpx visor add --category admin\n```\n\n| Component | CLI Name | Description |\n|-----------|----------|-------------|\n| Activity Feed | `activity-feed` | Timestamped event stream |\n| Bulk Action Bar | `bulk-action-bar` | Floating bar for multi-select actions |\n| Confirm Dialog | `confirm-dialog` | Destructive action confirmation modal |\n| Data Table | `data-table` | Sortable, filterable table with pagination |\n| Empty State | `empty-state` | Zero-data placeholder with CTA |\n| Filter Bar | `filter-bar` | Composable filter chip row |\n| Infographic Bar | `infographic-bar` | Continuous stat-card band with hairline dividers |\n| Kbd | `kbd` | Keyboard shortcut display |\n| Matrix Table | `matrix-table` | Members×roles boolean assignment grid |\n| Page Header | `page-header` | Title + actions header for admin pages |\n| Stat Card | `stat-card` | KPI metric card with trend |\n| Status Badge | `status-badge` | Semantic status indicator |\n\n### Blocks\n\n19 full-page and section-level blocks. Add with `--block`:\n\n```sh\nnpx visor add admin-dashboard --block\nnpx visor add hero-section --block\n```\n\n| Block | CLI Name | Category |\n|-------|----------|----------|\n| Admin Dashboard | `admin-dashboard` | Admin |\n| Admin Detail Drawer | `admin-detail-drawer` | Admin |\n| Admin List Page | `admin-list-page` | Admin |\n| Admin Settings Page | `admin-settings-page` | Admin |\n| Admin Shell | `admin-shell` | Admin |\n| Admin Tabbed Editor | `admin-tabbed-editor` | Admin |\n| Admin Wizard | `admin-wizard` | Admin |\n| CTA Section | `cta-section` | Marketing |\n| Features Grid | `features-grid` | Marketing |\n| Footer Section | `footer-section` | Marketing |\n| Hero Section | `hero-section` | Marketing |\n| Pricing Section | `pricing-section` | Marketing |\n| Steps Section | `steps-section` | Marketing |\n| Testimonial Section | `testimonial-section` | Marketing |\n| Login Form | `login-form` | Auth |\n| Configuration Panel | `configuration-panel` | Configuration |\n| Design System Deck | `design-system-deck` | Documentation |\n| Design System Specimen | `design-system-specimen` | Documentation |\n| Sphere Playground | `sphere-playground` | Visual |\n\n### Available Hooks\n\n**General (10)**\n`use-boolean` · `use-click-outside` · `use-currency` · `use-debounce` · `use-focus-trap` · `use-intersection-observer` · `use-keyboard-shortcut` · `use-local-storage` · `use-media-query` · `use-previous`\n\n**Deck (4)**\n`use-intersection-animation` · `use-keyboard-nav` · `use-slide-engine` · `use-wheel-nav`\n\n```sh\nnpx visor add use-boolean\nnpx visor add use-debounce\nnpx visor add use-slide-engine\n```\n\n---\n\n## How It Works\n\nWhen you run `npx visor add button`, two files land in your project:\n\n```\nyour-project/\n├── components/\n│   └── ui/\n│       └── button/\n│           ├── button.tsx           ← React component (yours to edit)\n│           └── button.module.css    ← Component styles (yours to edit)\n└── lib/\n    └── utils.ts                     ← cn() helper, added once and shared\n```\n\nComponents use CSS Modules for scoped class names and CSS custom properties from the tokens package for all design values:\n\n```css\n/* button.module.css */\n.base {\n  border-radius: var(--radius-md);\n  font-size: var(--text-sm);\n}\n\n.variantDefault {\n  background-color: var(--interactive-primary-bg);\n  color: var(--interactive-primary-text);\n}\n```\n\nVariants are managed with [CVA](https://cva.style):\n\n```tsx\n// button.tsx\nconst buttonVariants = cva(styles.base, {\n  variants: {\n    variant: {\n      default: styles.variantDefault,\n      secondary: styles.variantSecondary,\n    },\n    size: {\n      sm: styles.sizeSm,\n      md: styles.sizeMd,\n    },\n  },\n  defaultVariants: { variant: \"default\", size: \"md\" },\n})\n```\n\n---\n\n## Theming\n\nTheming is Visor's core differentiator. Every component references CSS custom properties — never hard-coded values. Swap the token values and the entire UI follows.\n\n### The 3-Tier Token Architecture\n\n```\nTier 1: Primitives         Tier 2: Semantic          Tier 3: Adaptive\n--color-gray-900    ──→    --text-primary      ──→   :root { --text-primary }\n--color-gray-50     ──→    --surface-page      ──→   .theme-dark { ... }\n--radius-lg         ──→    --border-default\n```\n\nComponents only reference Tier 2 (semantic) tokens. This means overriding a single semantic token updates every component that uses it.\n\n### Dark Mode\n\nVisor ships with a dark theme out of the box. Apply it by adding `.theme-dark` to your root element:\n\n```html\n\u003chtml class=\"theme-dark\"\u003e\n```\n\n### Overriding Tokens\n\nOverride any token after your `@import` statement — no forking required:\n\n```css\n/* globals.css */\n@import \"@loworbitstudio/visor-core\";\n\n:root {\n  /* Rebrand the primary color across the entire system */\n  --interactive-primary-bg: #6366f1;\n  --interactive-primary-bg-hover: #4f46e5;\n}\n\n.theme-dark {\n  --interactive-primary-bg: #818cf8;\n}\n```\n\n### Creating a Custom Theme\n\n```css\n/* styles/theme-brand.css */\n.theme-brand {\n  --surface-page: #0a0a14;\n  --surface-card: #12121f;\n  --text-primary: #f0f0ff;\n  --text-secondary: #a0a0c0;\n  --interactive-primary-bg: #6366f1;\n  --interactive-primary-text: #ffffff;\n  --border-default: rgba(255, 255, 255, 0.1);\n}\n```\n\n```tsx\n// app/layout.tsx\nexport default function RootLayout({ children }) {\n  return (\n    \u003chtml lang=\"en\" className=\"theme-brand\"\u003e\n      \u003cbody\u003e{children}\u003c/body\u003e\n    \u003c/html\u003e\n  )\n}\n```\n\n### Creating a Theme from `.visor.yaml`\n\nDefine your theme in a YAML file and generate framework-specific CSS:\n\n```yaml\n# .visor.yaml\nname: my-brand\nversion: 1\ncolors:\n  primary: \"#6366f1\"\n```\n\n```bash\n# Generate Next.js globals.css with @layer support\nnpx @loworbitstudio/visor theme apply .visor.yaml --adapter nextjs\n\n# Generate fumadocs bridge tokens\nnpx @loworbitstudio/visor theme apply .visor.yaml --adapter fumadocs\n\n# Generate scoped deck CSS\nnpx @loworbitstudio/visor theme apply .visor.yaml --adapter deck\n\n# Generate docs-site CSS (class-scoped, includes fumadocs bridge)\nnpx @loworbitstudio/visor theme apply .visor.yaml --adapter docs\n```\n\nRegister a theme in the Visor docs site in one command:\n\n```bash\n# Creates CSS file, updates globals.css and theme-config.ts\nnpx @loworbitstudio/visor theme register .visor.yaml --group \"Client\"\n\n# Preview changes without writing\nnpx @loworbitstudio/visor theme register .visor.yaml --group \"Client\" --dry-run\n\n# Remove a theme\nnpx @loworbitstudio/visor theme unregister my-brand\n```\n\nOr scaffold a complete themed project:\n\n```bash\nnpx @loworbitstudio/visor init --template nextjs\n```\n\n### FOWT Prevention\n\n\u003e Already wired automatically when you use `npx @loworbitstudio/visor init --template nextjs`. The steps below are only needed for manual setups or non-Next.js apps.\n\nFOWT prevention covers two orthogonal axes. Add the script(s) you need as blocking `\u003cscript\u003e` tags in your `\u003chead\u003e`, before any stylesheets.\n\n**Mode axis (dark/light).** Reads `localStorage('visor-theme')`, falls back to `prefers-color-scheme`, and sets `.dark` or `.light` on `\u003chtml\u003e` before first paint:\n\n```typescript\nimport { FOWT_SCRIPT } from '@loworbitstudio/visor-theme-engine/fowt';\n\n// In your layout.tsx \u003chead\u003e:\n\u003cscript\u003e{FOWT_SCRIPT}\u003c/script\u003e\n```\n\n**Theme-identity axis (palette).** For apps that switch between N registered themes at runtime, `generateThemeFowtScript` validates the stored theme name against an allowlist (falling back to a default), stamps it on `\u003chtml\u003e`, and enables exactly the matching inlined `\u003cstyle data-theme-css\u003e`:\n\n```typescript\nimport { generateThemeFowtScript } from '@loworbitstudio/visor-theme-engine/fowt';\n\nconst themeScript = generateThemeFowtScript({\n  themes: ['entr', 'space'],   // registered-theme allowlist\n  defaultTheme: 'entr',        // fallback when nothing valid is stored\n  // storageKey: 'visor-theme-name',  // optional, this is the default\n  // attribute: 'data-theme-name',    // optional, this is the default\n});\n\n// In your layout.tsx \u003chead\u003e, AFTER the inlined \u003cstyle data-theme-css=\"...\"\u003e tags:\n\u003cscript\u003e{themeScript}\u003c/script\u003e\n```\n\nBoth scripts are ES5-safe and can live in the same `\u003chead\u003e` — the mode axis toggles a class, the palette axis toggles which theme stylesheet is active.\n\n### Importing Specific Token Layers\n\n```css\n@import \"@loworbitstudio/visor-core/primitives\";   /* Tier 1: raw values */\n@import \"@loworbitstudio/visor-core/semantic\";     /* Tier 2: purpose-named */\n@import \"@loworbitstudio/visor-core/themes/light\"; /* Tier 3: light theme */\n@import \"@loworbitstudio/visor-core/themes/dark\";  /* Tier 3: dark theme */\n```\n\n### CSS Layer Architecture\n\nVisor's distributed CSS uses [CSS Cascade Layers](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) so generated themes win the cascade without consumer intervention.\n\nEvery shipped `dist/*.css` file declares the same layer order and wraps its content in the matching tier:\n\n```css\n@layer visor-primitives, visor-semantic, visor-adaptive, visor-bridge;\n```\n\n| Layer | Source | Purpose |\n| --- | --- | --- |\n| `visor-primitives` | `@loworbitstudio/visor-core/primitives` | Raw token values (colors, spacing, type) |\n| `visor-semantic` | `@loworbitstudio/visor-core/semantic` | Purpose-named tokens (`--text-primary`, `--surface-card`) |\n| `visor-adaptive` | `@loworbitstudio/visor-core/themes/*`, generated themes (`visor theme apply --adapter nextjs`) | Light/dark-aware tokens, generated theme overrides |\n| `visor-bridge` | Framework integrations (e.g. fumadocs) | Maps Visor tokens onto framework-native variables |\n\n**Cascade rules at a glance:**\n\n- Per the CSS spec, **unlayered styles always beat layered styles**. So your bare `:root { ... }` overrides written after `@import \"@loworbitstudio/visor-core\"` continue to win — that pattern still works as documented above.\n- **Generated themes win over visor-core defaults.** Both sit in `@layer visor-adaptive`, and last-loaded wins within a layer, so importing a generated theme after visor-core gives the theme its expected priority.\n- **Stock themes ship layered too.** When you import `@loworbitstudio/visor-core/themes/blackout` (or any other stock theme), the `.{slug}-theme` class still wins on selector specificity but its rules participate in `visor-adaptive` so they coexist cleanly with generated themes.\n\n---\n\n## Updating\n\n### Updating a Component\n\nRe-run the CLI with `--overwrite` to pull the latest upstream version:\n\n```sh\nnpx visor add button --overwrite\n```\n\nBecause you own the files, the CLI shows a diff before overwriting. If you've customized the component, use git to merge:\n\n1. Commit your customizations.\n2. Run `npx visor add button --overwrite`.\n3. Use `git diff` to review what changed.\n4. Merge your customizations into the updated version.\n5. Commit the result.\n\n### Updating Tokens\n\nToken updates are standard npm updates:\n\n```sh\nnpm update @loworbitstudio/visor-core\n```\n\nToken updates propagate automatically to all components. No component files change.\n\n---\n\n## CLI Reference\n\n```sh\n# Setup\nnpx @loworbitstudio/visor init                              # Create visor.json config\nnpx @loworbitstudio/visor init --template nextjs            # Initialize with Next.js template\n\n# Components\nnpx @loworbitstudio/visor add \u003ccomponent\u003e                   # Add a component, hook, or lib entry\nnpx @loworbitstudio/visor add \u003cc1\u003e \u003cc2\u003e \u003cc3\u003e                # Add multiple at once\nnpx @loworbitstudio/visor add --category \u003cname\u003e             # Add all items in a category\nnpx @loworbitstudio/visor add \u003ccomponent\u003e --block           # Add a block\nnpx @loworbitstudio/visor add \u003ccomponent\u003e --overwrite       # Update an existing component\nnpx @loworbitstudio/visor list                              # List all available components\nnpx @loworbitstudio/visor list --category \u003cname\u003e            # List by category\nnpx @loworbitstudio/visor diff [component]                  # Show local vs. registry differences\nnpx @loworbitstudio/visor suggest --for \"\u003cuse case\u003e\"        # Find components for a use case\nnpx @loworbitstudio/visor suggest --for \"\u003cuse case\u003e\" --json # JSON output (for AI agents)\n\n# Themes\nnpx @loworbitstudio/visor theme apply \u003cfile\u003e                # Generate CSS from .visor.yaml\nnpx @loworbitstudio/visor theme apply \u003cfile\u003e --adapter nextjs     # Next.js adapter\nnpx @loworbitstudio/visor theme apply \u003cfile\u003e --adapter nextjs --scope-prefix 'body.my-theme'  # Body-class scoped output\nnpx @loworbitstudio/visor theme apply \u003cfile\u003e --adapter fumadocs   # fumadocs adapter\nnpx @loworbitstudio/visor theme apply \u003cfile\u003e --adapter deck       # Deck adapter\nnpx @loworbitstudio/visor theme validate \u003cfile\u003e             # Validate a .visor.yaml theme\nnpx @loworbitstudio/visor theme export [file]               # Export theme to YAML/JSON\nnpx @loworbitstudio/visor theme extract                     # Extract .visor.yaml from existing CSS\nnpx @loworbitstudio/visor theme register \u003cfile\u003e             # Register theme in the docs site\nnpx @loworbitstudio/visor theme unregister \u003cslug\u003e           # Remove a theme from the docs site\nnpx @loworbitstudio/visor theme sync                        # Re-generate CSS for all themes\n\n# Fonts\nnpx @loworbitstudio/visor fonts add \u003cpath\u003e --org \u003cname\u003e     # Upload woff2 to Visor Fonts CDN\n```\n\nAll commands support `--json` for structured output (useful for AI agents and scripts).\n\n---\n\n## AI Agent Consumability\n\nVisor includes structured metadata that makes it easy for AI agents to discover, understand, and compose components without reading source code.\n\n**Per-component metadata** — Each component has a `.visor.yaml` file alongside its source with props, variants, slots, dependencies, usage examples, and \"when to use\" / \"when not to use\" guidance.\n\n**Registry manifest** — `visor-manifest.json` is auto-generated during build, aggregating all component metadata (including auto-extracted CSS tokens) into a single file an agent can load.\n\n**Composition patterns** — Pattern files in `patterns/` document how components combine for common use cases (form with validation, dashboard layout, data table with filters).\n\nSee [docs/ai-consumability.md](docs/ai-consumability.md) for the full spec.\n\n---\n\n## Stack\n\n- **React + TypeScript**\n- **CSS Modules** + CSS custom properties (no Tailwind, no CSS-in-JS)\n- **[CVA](https://cva.style)** for variant management\n- **[Radix UI](https://radix-ui.com)** for accessible primitives\n- **[Phosphor Icons](https://phosphoricons.com)**\n- **[Vitest](https://vitest.dev) + [React Testing Library](https://testing-library.com/react)** for testing\n- **[fumadocs](https://fumadocs.vercel.app)** for the documentation site\n\n---\n\n## Documentation\n\nFull documentation, component previews, and a props reference are available at:\n\n**[visor.loworbit.studio](https://visor.loworbit.studio)**\n\n---\n\n## Built with Visor\n\n- **[Kaiah](https://github.com/low-orbit-studio/kaiah)** — AI-powered marketing platform\n- **[Blacklight](https://github.com/low-orbit-studio/blacklight)** — Music industry intelligence tool\n\nUsing Visor in your project? [Open a PR](https://github.com/low-orbit-studio/visor/edit/main/README.md) to add it here.\n\n---\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on submitting components, token changes, and bug fixes.\n\nTo develop locally:\n\n```sh\ngit clone https://github.com/loworbit/visor.git\ncd visor\nnpm install\n\nnpm test               # Run tests\nnpm run typecheck      # Type check\nnpm run lint           # Lint\nnpm run build          # Build all packages\nnpm run docs:dev       # Start docs site\nnpm run widgetbook:dev         # Start Flutter widgetbook preview (requires Flutter SDK)\nnpm run themes:apply-flutter  # Regenerate packages/visor_themes/ for all 11 themes\n```\n\n### Changesets (every shipping-package change)\n\nEvery PR that touches shipping-package source needs a `.changeset/*.md` file. The `Changeset Gate` workflow blocks merge if one is missing or malformed.\n\n**Automatic generation (recommended).** The pre-push git hook runs `scripts/generate-changeset.mjs` before every push. If the diff touches a shipping path (any directory listed in `changeset-paths.json` — `components/`, `blocks/`, `hooks/`, `lib/`, `registry/`, `themes/`, `patterns/`, `assets/`, or the `src/`/`lib/` trees of the published packages) and no operator-authored changeset exists yet, Claude will write `.changeset/\u003cbranch-slug\u003e.md` and stage it automatically. The same `changeset-paths.json` drives the CI changeset gate, so the local hook and CI stay in sync.\n\nRequirements: `claude` CLI must be installed globally (`npm install -g @anthropic-ai/claude-code`). If it's not available, the hook prints a warning and the push proceeds normally.\n\n**Manual generation.** Run at any time:\n\n```sh\nnode scripts/generate-changeset.mjs\n# or the standard interactive way:\nnpm run changeset\n```\n\n**On-demand via Claude Code.** The `/lo-changeset` skill at `.claude/skills/lo-changeset/SKILL.md` wraps the same script:\n\n```\n/lo-changeset\n```\n\n**Bypass the hook.** Skip changeset generation for a push:\n\n```sh\ngit push --no-verify\n```\n\n**Auto-generated marker.** Generated changesets include `# generated-by: lo-changeset` in their YAML frontmatter. If you edit the changeset and remove that marker, it becomes operator-authored — the hook will not overwrite it on subsequent pushes. Operator overrides always win.\n\n**Failure handling.** If `claude` fails for any reason, the hook exits 0 and the push proceeds. Run `npm run changeset` manually if you need a minor/major bump and the auto-generation failed.\n\n**Prompt source.** `scripts/changeset-prompt.md` contains the bump-type rules and output format. Edit it to tune the AI's behavior.\n\n### Repository Structure\n\n```\nvisor/\n├── components/ui/     # Component source + .visor.yaml metadata\n├── hooks/             # Hook source (registry entries)\n├── lib/               # Utility source (registry entries)\n├── patterns/          # Composition patterns (.visor-pattern.yaml)\n├── registry/          # Registry schema and definitions\n└── packages/\n    ├── cli/           # @loworbitstudio/visor CLI + manifest builder\n    ├── tokens/        # @loworbitstudio/visor-core npm package\n    ├── visor-flutter/ # visor_core Flutter package (pub.dev)\n    ├── visor_themes/  # All 11 Visor ThemeData — generated, do not edit\n    ├── widgetbook/    # Flutter widgetbook preview app\n    └── docs/          # fumadocs documentation site\n```\n\n### Flutter widget quality\n\nEvery `visor_*` Flutter widget is audited against the [Flutter Widget Quality Contract](./docs/flutter-widget-quality-contract.md) — a tiered checklist (Required / Recommended / Stretch) covering tokens, semantics, touch targets, reduce-motion, RTL, tests, and a11y matchers. Required-tier compliance gates a widget being marked production-ready.\n\n---\n\n## Operator workflows\n\nDay-to-day publishing is automatic for the three public npm packages — `.changeset/*.md` files written on each PR drive the bumps, and `release.yml` opens a \"Version Packages\" PR that publishes on merge. `@low-orbit-studio/visor-themes-private` still auto-versions on its own merges. The commands below surface only for the rare cases where a human is in the loop: health checks and cross-repo coordinated releases.\n\n### Publishing health and coordinated releases\n\n`/lo-visor-publish` (see [`.claude/skills/lo-visor-publish/SKILL.md`](./.claude/skills/lo-visor-publish/SKILL.md)) has two modes:\n\n- **`status`** — read-only drift report across all 4 publishable artifacts. Non-zero exit on drift, so it can gate other workflows.\n  ```bash\n  node scripts/visor-publish-status.mjs\n  ```\n- **`coordinate \u003cvisor-PR\u003e \u003cthemes-PR\u003e`** — single-confirmation cross-repo release for the case where a feature spans Visor + visor-themes-private and both must ship together.\n  ```bash\n  node scripts/visor-publish-coordinate.mjs 369 2 --dry-run   # preview only\n  node scripts/visor-publish-coordinate.mjs 369 2             # live\n  ```\n\nThe skill itself contains no publish logic. Each repo's existing CI (`release.yml` on the Visor side, themes-private's `publish.yml`) remains the source of truth for what publishes. See [`docs/audits/publish-automation.md`](./docs/audits/publish-automation.md) for the full audit.\n\n### Publish-gate audit (PR comment governance)\n\nWhen the `visor-publish-smoke` workflow detects drift between the source on `main` and the latest published `@loworbitstudio/visor` tarball, the audit step maps each drifted primitive back to the PR that landed it and posts a comment there — so \"merged\" eventually catches up with \"shipped.\" Uses the built-in `GITHUB_TOKEN`, no extra secrets required. Run it locally with `npm run audit:publish`. Full background in [`CLAUDE.md` § Publish Gate](./CLAUDE.md#publish-gate) and [`docs/wisdom/W029-vi-ticket-publish-governance.md`](./docs/wisdom/W029-vi-ticket-publish-governance.md).\n\n---\n\n## Sustainability\n\nVisor is free and open-source, built and maintained by [Low Orbit Studio](https://loworbit.studio). If it's useful to you, here's how to support it:\n\n- **Use it and share it** — the best support is adoption and word of mouth.\n- **Contribute** — bug reports, PRs, and Discussions participation all help.\n- **Hire us** — Low Orbit Studio takes on product and design system work. [Get in touch](https://loworbit.studio).\n\n---\n\n## License\n\nSee [LICENSE](LICENSE) for details.\n\n---\n\nBuilt by [Low Orbit Studio](https://loworbit.studio) — Brooklyn, NY.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flow-orbit-studio%2Fvisor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flow-orbit-studio%2Fvisor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flow-orbit-studio%2Fvisor/lists"}