HTML
No CLI, no build step, no framework — link the stylesheets straight from jsDelivr and use the .jl-* classes directly on plain HTML elements.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/button.css">
</head>
<body>
<button class="jl-btn jl-btn--primary jl-btn--md">Click me</button>
</body>
</html>How the stylesheets are organized
css/index.cssships the design tokens (see Theming), base resets, and the Geist font@import. Always include it first — every component's classes are built on these tokens.- Each component has its own
css/<name>.csswith just that component's.jl-*classes (e.g.css/button.css→.jl-btn,.jl-btn--primary,.jl-btn--md, …).
Only link the component stylesheets you actually use.
All-in-one bundle
Prototyping, or don't want to manage individual links? Link css/all.css — a single bundle that pulls in the tokens (index.css) plus every component stylesheet. It's the only file you need:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/css/all.css">This is the most convenient option but ships the CSS for every component. For production sites where bundle size matters, prefer linking index.css + just the component files you use.
Interactivity (optional)
Most components are pure CSS or native HTML controls and need no JavaScript. A few need a little behavior — Snippet's copy button, Alert/Banner dismiss, and (as they land) the overlay components like Dialog, Drawer, Dropdown, and Tabs. Drop in the JLDS behavior layer and it wires them up automatically:
<script src="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/js/all.js" defer></script>It's progressive enhancement: the markup renders correctly without it; the script only adds behavior. On load it scans the page for .jl-* markup and initializes it. For content you inject later (e.g. after a fetch), call JLDS.init(container) to wire up just that subtree:
const el = document.querySelector("#new-content")
el.innerHTML = await (await fetch("/fragment.html")).text()
JLDS.init(el) // activate any .jl-* behavior insideWant only what you use? Each behavior also ships as js/<name>.js — load js/core.js and the shared js/util.js first, then the component files you need:
<script src="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/js/core.js" defer></script>
<script src="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/js/util.js" defer></script>
<script src="https://cdn.jsdelivr.net/gh/jarooda/jlds@main/registry/js/snippet.js" defer></script>js/util.js holds shared DOM helpers (JLDS.util.copy, click-outside, escape, scroll-lock, focus-trap) that the behaviors build on — the all.js bundle already includes it.
This is opt-in, unlike the React/Vue components (which carry their own behavior in the copied source). The behaviors are idempotent and dependency-free.
Single source of truth
registry/css/<name>.css is the only place a component's styles are written. It's served directly to HTML users via jsDelivr, and it's what jlds add fetches and writes into your project as <name>.css for React and Vue. The CDN file, the React .css import, and the Vue <style src="..."> file are always identical.
Pinning a version
@main always reflects the latest commit. For production, pin to a release tag so the CSS never changes underneath you:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/[email protected]/registry/css/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jarooda/[email protected]/registry/css/button.css">See Registry: How it works for more on how files are organized and versioned.