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 🙏

© 2025 – Pkg Stats / Ryan Hefner

vite-static-assets-plugin

v1.2.2

Published

Typesafe static assets with Vite

Readme

Vite Static Assets Plugin

A Vite plugin that automatically scans your static assets directory, generates a type-safe TypeScript module with all asset paths, directory-aware types, and a helper function to get asset URLs. It validates asset references during build and updates live during development.


Features

  • 🚀 Automatic Recursive Scanning: Scans a directory (default: public) for all static assets.
  • 🛡 Type-Safe API: Generates a union type StaticAssetPath of all valid asset paths.
  • 📁 Directory-Aware Types: Generates StaticAssetDirectory and a powerful FilesInFolder<Dir> generic for directory-specific asset typing.
  • 🔗 Helper Function: Provides staticAssets() to get the URL for an asset, with runtime validation.
  • 🛠 Highly Configurable: Customize directory, output file, ignore patterns, debounce, directory depth, empty directory handling, leading slash, and more.
  • 🔄 Live Updates: Watches the directory in development mode and regenerates types on changes.
  • 🧭 Validation: Validates asset references and directory references during build, with detailed error messages.
  • Fast: Minimal overhead, optimized for large projects.

Usage

Import the generated function and types:

import { staticAssets, StaticAssetPath, StaticAssetDirectory, FilesInFolder } from './static-assets';

// Use the helper function
const logoUrl = staticAssets('images/logo.svg');

// Type-safe variables
const assetPath: StaticAssetPath = 'fonts/roboto.woff2';

const dir: StaticAssetDirectory = 'images/';


// Type-safe list of files directly inside 'icons/brands/'
type  Icons = FilesInFolder<'icons/brands/'>;
// use Icons type in your code
type Brands = {
  icon: Icons,
  name: string
}
// Create a list of brands with their icons and names
// get autocompletion and type checking!
const brands: Brands[] = [
  {
    icon: "icons/brands/coke.svg",
    name: "Coke"
  },
  {
    icon: "icons/brands/pepsi.svg",
    name: "Pepsi"
  },
  {
    icon: "icons/brands/rc-cola.svg",
    name: "RC Cola"
  },
  {
    icon: "icons/brands/dr-pepper.svg",
    name: "Dr Pepper"
  },
]

Installation

# npm
npm install --save-dev vite-static-assets-plugin

# yarn
yarn add -D vite-static-assets-plugin

# bun
bun add -d vite-static-assets-plugin

# pnpm
pnpm add -D vite-static-assets-plugin

Setup and Configuration

Add the plugin to your Vite config:

vite.config.ts

import { defineConfig } from 'vite';
import staticAssetsPlugin from 'vite-static-assets-plugin';

export default defineConfig({
  plugins: [
    staticAssetsPlugin({
      // Optional configuration (defaults shown):
      directory: 'public',
      outputFile: 'src/static-assets.ts',
      ignore: ['.DS_Store'],
      debounce: 200,
      enableDirectoryTypes: true,
      maxDirectoryDepth: 5,
      allowEmptyDirectories: false,
      addLeadingSlash: true,
    })
  ]
});

Generated TypeScript Module

The plugin generates a TypeScript file (default: src/static-assets.ts) containing:

StaticAssetPath

A union of all asset paths:

export type StaticAssetPath =
  'images/logo.svg' |
  'images/banner.jpg' |
  'fonts/roboto.woff2';

StaticAssetDirectory

A union of all directories containing assets, including '.' for the root:

export type StaticAssetDirectory =
  '.' |
  'fonts/' |
  'images/' ;

FilesInFolder<Dir>

A generic type representing only the files directly inside a directory:

// Example: all files directly inside 'images/' (not nested)
type ImageFiles = FilesInFolder<'images/'>;
// 'logo.svg' | 'banner.jpg'

staticAssets(path)

A function that returns the URL for an asset, with validation:

export function staticAssets(path: StaticAssetPath): string;

If you pass an invalid path, it throws an error at runtime and TypeScript will catch it at compile time.


Use it in your components:

<img src={staticAssets('images/logo.svg')} alt="Logo" />

Framework Agnostic

Works with any frontend framework that uses Vite: React, Vue, Svelte, Angular, Solid, Lit, and more.


Plugin Options

| Option | Type | Default | Description | |--------------------------|-----------------|---------------------------|--------------------------------------------------------------------------------------------------| | directory | string | 'public' | Directory to scan for static assets | | outputFile | string | 'src/static-assets.ts' | Path to generate the TypeScript module | | ignore | string[] | ['.DS_Store'] | Glob patterns to ignore | | debounce | number | 200 | Debounce time (ms) for file watcher events | | enableDirectoryTypes | boolean | true | Generate directory-aware types (StaticAssetDirectory, FilesInFolder) | | maxDirectoryDepth | number | 5 | Maximum directory nesting level for directory type generation | | allowEmptyDirectories | boolean | false | Allow referencing empty directories in validation | | addLeadingSlash | boolean | true | Add a leading slash to generated asset URLs |


How It Works

  1. Scans the specified directory recursively, ignoring patterns.
  2. Generates a TypeScript file with:
    • StaticAssetPath union of all asset paths.
    • StaticAssetDirectory union of directories.
    • FilesInFolder<Dir> generic.
    • staticAssets() function.
  3. Watches the directory in development mode, regenerating on changes.
  4. Validates asset references and directory references during build.
  5. Throws errors with detailed info if assets or directories are missing.

Error Handling

  • If you reference a missing asset in staticAssets(), the plugin throws a build-time error with details (even if you're skipping TS typechecking before build).
  • If you reference a directory (via FilesInFolder or in code) that is empty or missing, it throws an error unless allowEmptyDirectories: true.
  • Errors include the file path, missing asset/directory, and suggestions.
  • Please note that this message is shown in case you actually skip TS typechecking before build. In case you're not typechecking before build (which is recommended), the error will be thrown at build time and you'll see the full error message in the terminal.

TypeScript Integration

  • The generated file is TypeScript-ready (as long as you set outputFile in your vite.config.ts to folder that is visible to your project).
  • Enjoy auto-completion, type checking, and refactoring support for your static assets.

Development

Testing

This project uses Vitest:

# Run all tests
npm test

# Watch mode
npm run test:watch

# Coverage
npm run test:coverage

Tests are in packages/plugin/tests/ and cover core functions and plugin behavior.


License

MIT


Contributing

Contributions, issues, and feature requests are welcome! Please open an issue or pull request.