Styling (Tailwind v4)
Tailwind v4 is auto-loaded in every web app's Vite pipeline. The mandatory @source glob, @theme design tokens, and the two silent-failure gotchas (the framework root is .framework/, not src/; a second @theme after @layer is dropped).
Every Voltro web app's Vite pipeline auto-loads @tailwindcss/vite. Apps that
don't use Tailwind pay no runtime cost (the plugin emits nothing when no
@import "tailwindcss" appears in any CSS file).
To use it:
/* src/globals.css */
@import "tailwindcss";
/* IMPORTANT: the framework's Vite root is `<app>/.framework/`, not
`<app>/src/`. Without @source, Tailwind's content scanner misses every .tsx
file under src/ — you get an empty `@layer utilities` and zero applied
styles. The path is relative to THIS css file. */
@source "./**/*.{tsx,ts,jsx,js}";
@theme {
--color-background: #0a0a0a;
--color-foreground: #fafafa;
--radius: 0.5rem;
}// src/pages/layout.tsx
import '../globals.css'Tailwind v4's @theme block doubles as the framework's design-tokens surface —
define your colours / radii / fonts there once and they become available as
bg-background, text-foreground, etc. The shadcn convention works directly on
top: copy a component's source, the classes resolve.
Gotcha: keep ALL
@themeblocks ABOVE any@layerrules in the same stylesheet. A second@themeblock placed AFTER@layer baseis silently dropped by Tailwind v4 — none of its tokens are emitted.
Using @voltro/ui-shadcn — the kit @source is mandatory
If your app imports @voltro/ui-shadcn/tokens.css, you MUST declare a SECOND
@source pointing at the kit's source — otherwise every class that exists ONLY
inside a kit component (animations like motion-safe:animate-mesh-drift-a,
motion-safe:animate-twinkle, kit-internal prose variants) is silently dropped
from the generated CSS. The components mount and the keyframes register, but the
animate-* utility classes never resolve — no warning is emitted.
/* src/globals.css — app uses kit compositions */
@import "@voltro/ui-shadcn/tokens.css";
@source "./**/*.{tsx,ts,jsx,js}";
@source "../node_modules/@voltro/ui-shadcn/src/**/*.{tsx,ts,jsx,js}";Why: the kit's tokens.css ships its own @source "./**/*", but @source paths
resolve relative to the IMPORTING css file — so once your globals.css imports
the kit, the kit's ./**/* glob expands to YOUR app's src, not the kit's. The
kit's own components are then never scanned. Declaring the explicit kit path
closes the gap — the published package ships its src/ precisely so this glob
matches (workspace link and npm install alike).
How to verify: curl -sS http://localhost:<port>/@fs/<abs>/src/globals.css | grep animate- should list every kit animation utility you use. If a class is missing,
the @source is misconfigured.