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

@smoothcdn/loader

v1.0.4

Published

Smooth CDN framework-aware asset loader

Readme

@smoothcdn/loader

Framework-aware loader for Smooth CDN assets.

@smoothcdn/loader reads the same .scdn.json project configuration used by the Smooth CDN CLI and gives your app typed helpers and ready-to-use components for loading images, scripts, styles and fetchable assets from Smooth CDN.

It includes:

  • a framework-neutral core loader,
  • React and Next.js components/hooks for images, audio, video, scripts and styles,
  • Vue and Nuxt helpers,
  • Astro, SvelteKit and Remix entrypoints,
  • TypeScript asset typing generated from .scdn.json.

Image, media, script and style components share the same loading semantics as Smooth CDN HTML snippets. Use isCritical for assets needed above the fold; the loader then applies the correct loading attributes. Image responsiveness is driven only by imageVariants in .scdn.json.

Installation

npm install @smoothcdn/loader

Configuration

Place .scdn.json in the root of your project, generate the loader module, then call its bootstrap once from your app entrypoint.

scdn types
import { configureSmoothCDN } from "./smoothcdn-loader";

configureSmoothCDN();

After that, import components and helpers directly from @smoothcdn/loader. The generated file adds project asset types globally, so assetPath suggestions work without importing a project-specific wrapper in every component.

The loader expects the standard Smooth CDN config shape:

{
  "userSlug": "your-team",
  "projectSlug": "frontend-app",
  "version": "1.0.0",
  "sources": ["./public/*", "./dist/**/*"],
  "excludes": ["./public/*.txt", "./dist/**/*.map"],
  "replacePath": {
    "/dist/": "/assets/"
  },
  "imageVariants": {
    "mobile": 360,
    "tablet": 720,
    "desktop": 1600
  }
}

Use replacePath when files are collected from one location but should be referenced from another public path. replacePaths is also accepted as an alias.

URLs use the standard Smooth CDN path:

buildUrl("/public/logo.svg");
// https://cdn.smoothcdn.com/<userSlug>/<projectSlug>/<version>/public/logo.svg

// When version is not configured:
// https://cdn.smoothcdn.com/<userSlug>/<projectSlug>/public/logo.svg

TypeScript Asset Typing

The package exposes a generator that reads root .scdn.json, scans configured sources, applies excludes and replacePath, and writes a TypeScript module with project asset types.

Generate the types with the Smooth CDN CLI:

scdn types

The command should generate:

smoothcdn-loader.ts

To write the file somewhere else:

scdn types --output src/smoothcdn-loader.ts

Once the generated module is included in your app bootstrap, components imported from @smoothcdn/loader use those generated asset types automatically:

import { CDNImage } from "@smoothcdn/loader/react";

export function Logo() {
  return <CDNImage assetPath="/public/logo.svg" alt="Smooth CDN" width={40} height={40} />;
}

Commit smoothcdn-loader.ts with your app if you want asset-path autocomplete to work without regenerating it on every install. The .scdn directory can stay ignored.

.scdn/*
!.scdn/

Core

Use the core loader when you need a CDN URL or an imperative load outside a component.

import { createLoader } from "@smoothcdn/loader";

const loader = createLoader();

// Build a CDN URL for href, src, metadata or third-party APIs.
const logoUrl = loader.url("/public/logo.svg");
document.querySelector("a.download-logo")?.setAttribute("href", logoUrl);

// Load browser assets imperatively.
await loader.script("/public/app.js");
await loader.style("/public/app.css");
await loader.image("/public/hero.png");

// Fetch a CDN-hosted JSON or XML asset.
const response = await loader.fetch("/public/data.json");
const data = await response.json();

React

import { CDNImage, useFetch, useImage } from "@smoothcdn/loader/react";

export function Logo() {
  return (
    <CDNImage
      assetPath="/public/logo.svg"
      alt="Smooth CDN"
      width={40}
      height={40}
    />
  );
}

export function Preview() {
  const { image, error } = useImage("/public/logo.svg");

  if (error) return null;
  return <span>{image ? "Loaded" : "Loading"}</span>;
}

export function DataBlock() {
  const { data } = useFetch("/public/data.json");

  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

Next.js

import { CDNAudio, CDNImage, CDNVideo, Script, Style } from "@smoothcdn/loader/next";

export default function Page() {
  return (
    <>
      <Style assetPath="/public/app.css" isCritical />
      <Script assetPath="/public/app.js" isCritical />

      <CDNImage
        assetPath="/public/logo.svg"
        alt="Smooth CDN"
        isCritical
        width={80}
        height={80}
      />

      <CDNAudio
        assetPath="/public/intro.mp3"
        controls
      />

      <CDNVideo
        assetPath="/public/demo.mp4"
        posterAssetPath="/public/demo-poster.jpg"
        isCritical
        controls
        width={1280}
        height={720}
      />
    </>
  );
}

Vue

<script setup lang="ts">
import { CDNImage, useImage } from "@smoothcdn/loader/vue";

const { image, error } = useImage("/public/logo.svg");
</script>

<template>
  <CDNImage
    asset-path="/public/logo.svg"
    alt="Smooth CDN"
    width="80"
    height="80"
  />

  <span v-if="image">Loaded</span>
  <span v-if="error">Failed</span>
</template>

Nuxt

Create a plugin that configures the loader once.

// plugins/smoothcdn.ts
import { configureSmoothCDN } from "../smoothcdn-loader";

export default defineNuxtPlugin(() => {
  configureSmoothCDN();
});

Use the Nuxt entrypoint in components or composables:

<script setup lang="ts">
import { createSmoothLoader, CDNImage } from "@smoothcdn/loader/nuxt";

const { url } = createSmoothLoader();
const logoUrl = url("/public/logo.svg");
</script>

<template>
  <CDNImage
    asset-path="/public/logo.svg"
    alt="Smooth CDN"
    width="80"
    height="80"
  />

  <a :href="logoUrl">Open logo</a>
</template>

Astro

---
import { createSmoothLoader } from "@smoothcdn/loader/astro";

const { url } = createSmoothLoader();
const logoUrl = url("/public/logo.svg");
---

<img src={logoUrl} alt="Smooth CDN" width="80" height="80" />

SvelteKit

Initialize the loader in a shared module:

// src/lib/smoothcdn.ts
import { createSmoothLoader } from "@smoothcdn/loader/sveltekit";

export const smoothcdn = createSmoothLoader();

Use it in a Svelte component:

<script lang="ts">
  import { smoothcdn } from "$lib/smoothcdn";

  const logoUrl = smoothcdn.url("/public/logo.svg");
</script>

<img src={logoUrl} alt="Smooth CDN" width="80" height="80" />

Or create a typed load helper:

import { createAssetLoad } from "@smoothcdn/loader/sveltekit";

export const load = createAssetLoad({
  assetPath: "/public/logo.svg",
  depends: ["smoothcdn:logo"],
  cacheControl: "public, max-age=3600"
});

Remix

import { createSmoothLoader, createStyleLink } from "@smoothcdn/loader/remix";

const { url } = createSmoothLoader();

export const links = () => [
  createStyleLink("/public/app.css")
];

export default function Route() {
  return (
    <img
      src={url("/public/logo.svg")}
      alt="Smooth CDN"
      width={80}
      height={80}
    />
  );
}

Generated Image Variants

If your .scdn.json contains imageVariants, generated type output also includes those labels as valid variants.

const loader = createLoader();

loader.image("/public/logo.png", "640");

When .scdn.json contains imageVariants, image components automatically build srcSet from those configured widths. When imageVariants is not configured, the same component renders a single CDN src.

isCritical controls loading behavior. Critical images get fetchpriority="high" and synchronous decoding. Non-critical images get loading="lazy" and async decoding.

import { CDNImage } from "@smoothcdn/loader/react";

export function HeroImage() {
  return (
    <CDNImage
      assetPath="/public/hero.png"
      alt="Hero"
      isCritical
      width={1536}
      height={1024}
    />
  );
}