Skip to content

Vanilla setup

For a plain-HTML project there is no server to inject anything, so the design system’s <head> is hard-coded once and reused on every page. This is the exact head the live previews on this site use.

Paste inside <head> on every page
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- design tokens the CSS reads for native <select> / date control chrome -->
<style>
:root {
--select-bg: url("/design-system/assets/section-icons/selector.svg");
--date-bg: url("/design-system/assets/section-icons/calendar.svg");
--optional-title: "Optional";
}
</style>
<!-- the compiled stylesheet (this docs site builds it from src/styles/ds-entry.css) -->
<link rel="stylesheet" href="/ds.css" />
<!-- theme: must run before first paint to avoid a flash of the wrong theme -->
<script>
(function () {
const theme = localStorage.getItem('theme') || 'system'
const className =
theme === 'system'
? window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light'
: theme
document.documentElement.classList.add(className)
})()
</script>
<!-- third-party libraries the components rely on -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/numeral.js/2.0.6/numeral.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/cdn.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/locale/en-US/cdn.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/animejs/dist/bundles/anime.umd.min.js" defer></script>
<!-- Preline: interactive primitives (dropdowns, overlays, tabs, …) — bundled with the design system -->
<script src="/design-system/assets/preline/preline.js" defer></script>
<!-- design system runtime globals + components -->
<script src="/design-system/js/runtime.js" defer></script>
<script src="/design-system/js/_defaults.js" defer></script>
<script src="/design-system/js/theme.js" defer></script>
<script src="/design-system/js/format.js" defer></script>
<script src="/design-system/js/animation.js" defer></script>
<script src="/design-system/js/link.js" defer></script>
<script src="/design-system/js/element.js" defer></script>
<script src="/design-system/js/validate.js" defer></script>
<script src="/design-system/js/shell.js" defer></script>
<script src="/design-system/js/content.js" defer></script>
<script src="/design-system/js/detail-drawer.js" defer></script>
<script src="/design-system/js/table.js" type="module"></script>
<script src="/design-system/js/embla-carousel.js" type="module"></script>
<script src="/design-system/js/input.js" type="module"></script>
  1. Token <style> — three CSS variables the stylesheet reads for native control chrome (--select-bg, --date-bg) and the “optional” field label (--optional-title).

  2. Stylesheet — the single stylesheet you compile (here /ds.css).

  3. Theme script — runs before paint to add light/dark to <html> and avoid a flash. It reads the saved theme from localStorage.

  4. Third-party librariesnumeral (number formatting), date-fns (+ its en-US locale) for dates, and anime for animation. Loaded from a CDN.

  5. Preline — interactive primitives (dropdowns, overlays, tabs).

  6. Runtime + componentsruntime.js (inline icons), _defaults.js (global config), then each component script.

index.html
<!doctype html>
<html lang="en">
<head>
<!-- ↑ paste the design system head from above here -->
</head>
<body class="bg-background font-geist text-foreground antialiased">
<main class="mx-auto max-w-3xl p-8">
<h1 class="text-2xl font-semibold">Hello, design system</h1>
<button type="button" class="button-fill-primary mt-4"><span>Primary action</span></button>
</main>
</body>
</html>