npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@softobotics/storefront-config

v0.1.6

Published

Resolves a Vendure Channel's branding/nav/footer/checkout custom fields into a validated storefront config, and a provider that applies it as CSS custom properties.

Readme

@softobotics/storefront-config

Resolves a Vendure Channel's branding/nav/footer/checkout custom fields into a validated, defaulted StorefrontConfig, and a <StorefrontConfigProvider> that applies the brand tokens as CSS custom properties.

Why this exists

Each tenant storefront should be reskinnable from the Vendure Channel's admin settings (color, radius, fonts, nav/footer toggles) without a redeploy of the storefront's own code. This package is the shared resolution/validation layer; it does not fetch data itself — the consuming app queries the Channel's custom fields (e.g. via @softobotics/storefront-vendure-client) and passes the raw result in.

Usage

import {resolveStorefrontConfig} from '@softobotics/storefront-config';

const config = resolveStorefrontConfig(activeChannel.customFields);
import {StorefrontConfigProvider} from '@softobotics/storefront-config';

export default function RootLayout({children}: {children: React.ReactNode}) {
    return (
        <html>
            <body>
                <StorefrontConfigProvider config={config}>{children}</StorefrontConfigProvider>
            </body>
        </html>
    );
}

CSS custom properties

StorefrontConfigProvider targets the exact token names vendure-storefront's globals.css already defines under its @theme inline block: --primary, --primary-foreground, --radius, --font-sans, --font-mono, plus the rest of its shadcn palette — --background, --foreground, --card, --card-foreground, --popover, --popover-foreground, --secondary, --secondary-foreground, --muted, --muted-foreground, --accent, --accent-foreground, --destructive, --border, --input, --ring — not invented --brand-* names. An unconfigured channel resolves to the same values already hardcoded there (every one of these was copied byte-for-byte from globals.css's :root block), so wiring this in is a no-op until a channel sets its own values.

--sidebar-* and --chart-* are deliberately not covered — neither renders anywhere in vendure-storefront's customer-facing UI (the sidebar shadcn primitive and the chart component are both unused there), so making them configurable would be dead surface area.

Dark mode

brand.dark mirrors the same set of tokens (plus primaryColor/ primaryForeground, which do change between light/dark) for the .dark class block next-themes toggles. StorefrontConfigProvider always renders both a :root { ... } and a .dark { ... } block; every dark.* field defaults to the exact value already hardcoded in globals.css's .dark block, so it's a no-op there too until configured.

The brandPrimaryColor/etc. custom fields

These scalar fields (brandPrimaryColor, brandPrimaryForeground, brandRadius, brandFontSans, brandFontMono, faviconAssetId) plus the JSON ones below must exist on the Vendure Channel entity's custom fields (see vendure-backend/src/vendure-config.ts) and have a migration generated and applied before a real channel can set them. Until that migration runs, resolveStorefrontConfig still works against an empty/undefined input and returns the documented defaults — it does not require the migration to exist to be built or tested.

storefrontThemeSettings

The rest of the palette (everything under "CSS custom properties" above, beyond brandPrimaryColor/brandPrimaryForeground) is bundled into one JSON text custom field, storefrontThemeSettings, rather than ~34 individual scalar fields (16 light + 18 dark tokens) — it's edited as one palette, not field-by-field, matching the existing storefrontNavSettings/storefrontFooterSettings/storefrontCheckoutSettings convention. Shape:

{
  "secondaryColor": "oklch(0.9 0.05 200)",
  "dark": { "primaryColor": "oklch(0.4 0.2 145)" }
}

Any key can be omitted — omitted keys fall back to their own documented default, same as every other field in this package.

Asset ids and logo/favicon URLs

logoAssetId/faviconAssetId are passed through as raw ids, unresolved to a URL — same as the existing logoAssetId field predating this package. Vendure's Shop API has no top-level asset(id) query, so resolving an id to a preview URL is left to the consuming app's existing convention; this package does not guess at one.

Until that resolution exists, prefer the separate logoUrl/faviconUrl fields — plain, already-resolved URLs (e.g. an external CDN link, or a Vendure asset's preview URL copied in manually) that a consumer can render directly with no extra lookup. resolveStorefrontConfig({}).brand.logoUrl is null until a channel sets one.

JSON-encoded fields

storefrontNavSettings, storefrontFooterSettings, and storefrontCheckoutSettings are stored as Vendure text custom fields containing JSON, matching the partial shape of NavConfig/FooterConfig/ CheckoutConfig. Malformed JSON is ignored (with a console.warn) and falls back to defaults rather than throwing — a misconfigured channel should degrade gracefully, not break the storefront build.