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

designertool-cdn-loader

v0.0.3

Published

A thin, dependency-free loader for the [Postcard Designer Tool](https://www.npmjs.com/package/designertool). It exposes the **same public API** as the `designertool` package (`register` and `PostcardDesignerElement`), but instead of bundling the Vue app i

Readme

designertool-cdn-loader

A thin, dependency-free loader for the Postcard Designer Tool. It exposes the same public API as the designertool package (register and PostcardDesignerElement), but instead of bundling the Vue app it loads the published bundle from a CDN at runtime.

This means your app ships a tiny package and always picks up the current Designer bundle, without re-installing or re-bundling on every Designer release.

Why use it

  • Drop-in API parity. register and PostcardDesignerElement match the designertool exports.
  • Tiny footprint. No Vue/Pinia in your dependency tree — the loaded bundle brings its own runtime.
  • Always current. Defaults to the latest published designertool on jsDelivr; pin a version when you need stability.
  • Safe by default. HTTPS-only for remote hosts, credential-omitting CORS, optional Subresource Integrity, request timeouts, and an optional fallback CDN.
  • SSR-safe. Importing the module never touches window, document, or customElements.

Installation

npm install designertool-cdn-loader

Quick start

import { register } from 'designertool-cdn-loader';

// Defines the <postcard-designer> custom element (loads the bundle on first use).
await register();
<postcard-designer></postcard-designer>

Because the bundle loads asynchronously, register() and PostcardDesignerElement.get() return Promises — designertool's own register() is synchronous, so if you migrate between the two, await the loader's version before relying on the element being defined.

Configuring the loader

setLoaderConfig() is an addition over the designertool surface — it controls where and how the bundle is fetched. Call it before the first API call that triggers a load; once loading begins, cdnUrl and version are locked.

import { setLoaderConfig, register } from 'designertool-cdn-loader';

setLoaderConfig({
  version: '0.73.0',         // omit or leave empty for "latest"
  timeoutMs: 15000,          // default 10000; valid range [1000, 120000]
});

await register();

LoaderConfig options

| Option | Type | Default | Notes | | --- | --- | --- | --- | | cdnUrl | string | jsDelivr (see below) | Base URL for a self-hosted bundle. Empty/whitespace uses the default. Trailing slash is normalized. Must be HTTPS (except localhost/loopback). | | version | string | latest | Pinned semver version, or latest when absent/empty. | | fallbackCdnUrl | string | — | Secondary base, attempted exactly once if the primary fails. | | timeoutMs | number | 10000 | Per-attempt timeout. Must be within [1000, 120000]. | | integrity | { js? } | — | SRI hash applied to the module request. Only useful with a pinned version. |

How the module URL is composed

With no cdnUrl set, the loader fetches the designertool npm package straight from jsDelivr using jsDelivr's npm URL scheme:

https://cdn.jsdelivr.net/npm/designertool@{version}/dist/designertool.js

With a custom cdnUrl (self-hosted), a plain directory layout is used instead:

{cdnUrl}/{version}/designertool.js

There is no separate CSS asset — the Designer bundle inlines its styles into the custom element's shadow DOM.

Note on latest: jsDelivr caches version resolution, so a newly published designertool release can take a while to show up under @latest. Pin a version if you need a release immediately.

Configuring the designer

The published designertool package is configured through the custom element itself (see the designertool README). The loader adds nothing here — whatever works against designertool works against the loaded bundle, because it is the same bundle.

API reference

| Export | Signature | Description | | --- | --- | --- | | register | () => Promise<void> | Defines <postcard-designer>. Idempotent; browser-only. | | PostcardDesignerElement | { get(): Promise<CustomElementConstructor> } | Lazily resolves the custom element constructor from the loaded bundle. | | setLoaderConfig | (config: LoaderConfig) => void | Configure the loader (see above). Loader-only. | | getLoadingState | () => 'loading' \| 'loaded' \| 'error' | Synchronous read of the current load state, for loading indicators. Loader-only. |

Tracking load state

import { getLoadingState, register } from 'designertool-cdn-loader';

register().catch((err) => {
  // err.category names the failure: 'js-load', 'timeout', 'integrity',
  // 'version-not-found', 'both-cdn-failed', 'insecure-url', ...
  // err.attemptedUrls lists the CDN URL(s) that were tried.
  console.error('Designer failed to load:', err.category, err.attemptedUrls);
});

console.log(getLoadingState()); // 'loading' | 'loaded' | 'error'

Behavior notes

  • Single load. Exactly one network load is ever in flight; all callers share one promise. Once loaded, subsequent calls reuse it with no new request.
  • Retry on failure. After a failed load, the next bundle-requiring call starts exactly one new attempt.
  • process shim. The published bundle is built for consumption through a bundler and references process.env.NODE_ENV; the loader installs a minimal globalThis.process = { env: { NODE_ENV: 'production' } } shim before importing it — only when no process global exists.
  • Non-browser environments. Bundle-requiring calls surface a browser-only error and issue no network request when window/document are undefined.

Local end-to-end testing

The automated test suite mocks all network I/O. To exercise the loader against a real, locally served bundle, see example/README.md.

Development

npm ci
npm run type-check
npm test
npm run build:npm

License

See the repository root.