vd3 Architecture Guide

vd3 is a single, standalone Vue 3 package. Everything is generated in one direction — design tokens → generated color CSS → absorbed component CSS → typed components & composables — so the styling and the behaviour always agree on the same --vd-* tokens and vd-* classes. There is no separate runtime to boot: the components are the runtime.

1
Design tokens (DTCG)

The source of truth lives as DTCG-format JSON under tokens/ (primitive scales, semantic colors, customizer metadata). Nothing above this layer hard-codes a hex value.

2
Generated color CSS

The token build turns that JSON into --vd-* custom-property layers — raw scales plus an active palette with a [data-palette] switch — and a flat tokens.json for design tooling.

3
Absorbed component CSS

The CSS build inlines the generated token layers together with the core, primitive, component, utility and effect stylesheets into one bundle — the whole design system in a single import.

4
Vue components & composables

Typed Vd* single-file components and useX composables read those same tokens/classes at runtime. They ship as a tree-shakeable ESM/CJS barrel with .d.ts types.

What you import

Each layer above surfaces as a stable published entry point. A Vue app only ever touches two of them; the rest are there for tooling.

Entry pointWhat it is
@vanduo-oss/vd3The typed, tree-shakeable barrel: every Vd* component, every useX composable, the VanduoVue plugin, and shared types.
@vanduo-oss/vd3/cssThe full absorbed stylesheet — tokens, layout, every component, utilities, effects, and the bundled icon font. Import once.
@vanduo-oss/vd3/css/coreThe same stylesheet without the bundled Phosphor icon fonts, for apps that supply their own icons.
@vanduo-oss/vd3/tokens.jsonThe flat { "--vd-name": value } token map (Figma-ready), for design tooling and codegen.
The build chain

The layers are produced by a deterministic, top-to-bottom build. You never run it — you install the prebuilt dist/ — but it shows how one source of tokens becomes CSS and components:

# How the package is built (you consume the prebuilt dist/)
clean-dist         # wipe dist/
build-tokens.mjs   # DTCG JSON  ->  generated color CSS + tokens.json
build-css.mjs      # inline every layer  ->  vd3.min.css (+ core, icon-free)
vite build         # SFCs  ->  ESM/CJS barrel
vue-tsc            # emit .d.ts types
check-class-coverage.mjs   # verify every documented class ships
Wiring an app

Consuming it is two imports: the stylesheet once, and the VanduoVue plugin for theme defaults. That is the whole setup.

// main.ts — the entire vd3 wiring, no runtime to bootstrap
import { createApp } from 'vue';
import { VanduoVue } from '@vanduo-oss/vd3';
import '@vanduo-oss/vd3/css';          // absorbed component CSS, one import
import App from './App.vue';

createApp(App).use(VanduoVue).mount('#app');
No global runtime

Behaviour is not injected by a global object that scans the DOM. Every interactive piece is a Vue component or composable that wires its own listeners on mount and cleans them up on unmount — reactive, tree-shakeable, and tied to the component lifecycle.

// Behaviour ships as plain Vue — components own their own lifecycle
import { VdModal, VdToast } from '@vanduo-oss/vd3';
import { useToast, useTheme } from '@vanduo-oss/vd3';

// A composable wires listeners on mount and tears them down on unmount;
// there is no global registry and no imperative DOM scan to remember.
const toast = useToast();
toast.success('Saved');

There is no standalone script to load and no global object to initialise — the package is pure Vue, so it tree-shakes with your app and cleans up with your components.