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

vite-plugin-layer

v0.0.2

Published

Cross-framework Vite plugin bringing Nuxt-Layer-style shared-base + extends/override to React, Svelte and Vue.

Downloads

298

Readme

vite-plugin-layer

Nuxt-Layer-style shared base layer + per-project inherit & override, as a cross-framework Vite plugin. React / Svelte / Vue (and any framework Vite supports) can all extends the same base.

Three pillars, all driven from one layer() call:

| Capability | Mechanism | | :-- | :-- | | Config inheritance / override merge | c12 + defuvirtual:layer-config | | Shared code reuse (#base/*) | Vite alias | | Auto-import (utils/ without import) | unimport (React out of the box; Svelte/Vue via a flag) |

Install

pnpm add -D vite-plugin-layer

vite is a peer dependency (>=5).

Usage

Declare a base layer's defaults in layer.config.ts, then have each app extends it.

// layers/base/layer.config.ts
import { defineLayerConfig } from 'vite-plugin-layer'

export default defineLayerConfig({
    app: { name: 'Base Layer', poweredBy: 'vite-plugin-layer' },
    apiBase: 'https://api.example.com',
})
// app vite.config.ts
import { defineConfig } from 'vite'
import { layer } from 'vite-plugin-layer'

export default defineConfig(async () => ({
    plugins: [
        framework(), // react() / svelte() / vue()
        await layer({
            extends: ['../layers/base'], // also supports c12 remote sources like 'github:org/base'
            app: { name: 'My App' }, // overrides the same-named field in base
        }),
    ],
}))

Config can instead live in the app's own layer.config.ts — then layer() reads it with no args.

Framework auto-import

Names under base/utils/* are usable without an import. React works out of the box. Svelte and Vue need their imports injected into <script> / <script setup> before compile, so opt in with a flag — it's an enforce: 'pre' plugin, ordered automatically:

// svelte
plugins: [svelte(), await layer({ svelte: true })]

// vue
plugins: [vue(), await layer({ vue: true })]

// react — no flag needed
plugins: [react(), await layer()]

In your app code

import { request } from '@layer/base/http' // package name — same string you extends
import config from 'virtual:layer-config' // merged config across the extends chain
// formatMoney, formatDate, ... — auto-imported from base/utils, no import line

When a layer is a package, use its package name for both extends and imports (same string, no alias). extends accepts a path, a package name, or a remote github: source. For package-name extends, give the layer "main": "./layer.config.ts" so c12 can resolve its config.

For path-only layers the plugin provides fallback aliases: #base (nearest parent) and #layers/<name> (name from layer.config.ts name → package.json name → directory), mapped via tsconfig.json paths.

For TypeScript, add the ambient types in tsconfig.json:

{
    "compilerOptions": {
        "types": ["vite/client", "vite-plugin-layer/client"],
        "paths": { "#base/*": ["../layers/base/*"] }
    }
}

Options

layer(options):

| Option | Default | Description | | :-- | :-- | :-- | | extends | — | Base layer(s): relative/absolute path or c12 remote source (github:org/base) | | app / other fields | — | Inline config, merged over the extends chain (highest priority) | | cwd | process.cwd() | Starting directory for resolution | | configName | 'layer' | Config file name → layer.config.ts | | autoImportDirs | ['utils', 'composables'] | Directory names scanned into auto-import | | autoImportsDts | 'auto-imports.d.ts' | Path for the generated d.ts, or false to disable. e.g. 'types/layer-imports.d.ts' | | svelte / vue | false | Enable the framework's auto-import adapter (true or {}) |

Typed virtual:layer-config

Augment LayerConfigRuntime once in your app (same pattern as Vite's ImportMetaEnv) for precise types:

declare module 'vite-plugin-layer' {
    interface LayerConfigRuntime {
        app: { name: string }
        apiBase: string
    }
}

export {}

defineLayerConfig is generic too, so the config in layer.config.ts keeps its literal types.

First-time type generation

The auto-import .d.ts is generated by dev/build. To make it exist on a fresh checkout (before the first dev/build — e.g. for CI typecheck or opening the editor), run the bundled CLI on install:

{
    "scripts": {
        "prepare": "vite-plugin-layer prepare"
    }
}

No flags needed — the CLI resolves your Vite config and reads the layer() options straight from it (extends chain, custom autoImportsDts path, vue), so it works for any app as-is. --cwd <dir> targets a different directory. The same thing is available programmatically as prepare(options) (same options as layer()) for setups without a Vite config.

License

MIT