loupe
Two small runtime helpers for an app themed by design tokens: work out which context to apply on load, and load the web fonts your tokens reference. Zero dependencies, browser-only.
npm install @bezel-labs/loupe
resolveInitialContext
Picks the theme to apply on load, in order: URL ?context= → URL ?globals=context:<name> → localStorage → fallback ("default").
import { resolveInitialContext } from '@bezel-labs/loupe';
import { CONTEXTS } from './bezel/contexts';
const context = resolveInitialContext({ contexts: [...CONTEXTS] });
document.documentElement.classList.add(context);
Pass contexts, the generated list from bezel-kit, and a resolved value is only honored if it's a member. Values are also checked against an identifier allowlist, since they end up as a CSS class.
The ?globals=context:<name> form is Storybook's, which is what the Bezel preview panel sends. Reading it means a plain app embedded in the panel follows the context switcher without being a Storybook.
loadFonts
Injects a webfont stylesheet plus preconnect hints into <head>. Idempotent, so it's safe to call repeatedly.
import { loadFonts } from '@bezel-labs/loupe';
import { FONTS } from './bezel/fonts';
loadFonts([...FONTS]);
loadFonts(FONTS, { provider: 'bunny' });
Setting a font-family in CSS isn't enough on its own. Without the font resource the browser silently falls back, so your carefully chosen typeface never appears. This is the piece that loads it. Google Fonts is the default provider; Bunny Fonts is supported for a no-tracking alternative.
API
resolveInitialContext, loadFonts, fontsHref, buildHref, preconnectHosts, DEFAULT_CONTEXT, plus the Context, ResolveContextOptions, FontDef, FontProvider, FontsHrefOptions, and LoadFontsOptions types.