Assets Setup
Le-Kit ships a handful of static files that must be accessible at runtime from your web server. Without them, icons won't render and — if you use admin mode — the component property editor won't work.
The files you need to serve are:
- Runtime bundle — the lazy-loading JS/CSS entry points (from
node_modules/le-kit/dist/le-kit/) - Component assets — JSON icon definitions used by
<le-icon>(fromnode_modules/le-kit/dist/components/assets/) - Custom Elements Manifest — component metadata used by the admin-mode property editor (from
node_modules/le-kit/src/assets/custom-elements.json)
The simplest approach is to copy them all into a single directory under your public root, for example /public/le-kit/. The component assets must live in an assets/ sub-folder next to the bundle so that Stencil's
internal path resolver finds them automatically — no extra configuration needed in that case.
Expected directory structure
public/
└── le-kit/
├── le-kit.esm.js ← bundle entry (ES modules)
├── le-kit.js ← bundle entry (no-module fallback)
├── le-kit.css ← bundled styles
├── *.entry.js ← lazy-loaded component chunks
├── assets/
│ ├── icons/ ← JSON icon definitions
│ └── custom-elements.json
└── …Astro
The easiest way in an Astro project is vite-plugin-static-copy, which runs during the Vite build and dev server.
npm install -D vite-plugin-static-copyimport { defineConfig } from 'astro/config';
import { viteStaticCopy } from 'vite-plugin-static-copy';
export default defineConfig({
vite: {
plugins: [
viteStaticCopy({
targets: [
{
// Runtime bundle (JS + CSS entry points + lazy chunks)
src: 'node_modules/le-kit/dist/le-kit/*',
dest: 'le-kit',
},
{
// Icons — must live in assets/ next to the bundle
src: 'node_modules/le-kit/dist/components/assets/*',
dest: 'le-kit/assets',
},
{
// Custom Elements Manifest (required for admin mode)
src: 'node_modules/le-kit/src/assets/custom-elements.json',
dest: 'le-kit/assets',
},
],
}),
],
},
});Then load the bundle in your base layout:
<script type="module" src="/le-kit/le-kit.esm.js"></script>
<noscript><script src="/le-kit/le-kit.js"></script></noscript>Vite
The same vite-plugin-static-copy plugin works in any plain Vite project (Vue, Svelte, vanilla, etc.).
npm install -D vite-plugin-static-copyimport { defineConfig } from 'vite';
import { viteStaticCopy } from 'vite-plugin-static-copy';
export default defineConfig({
plugins: [
viteStaticCopy({
targets: [
{
src: 'node_modules/le-kit/dist/le-kit/*',
dest: 'le-kit',
},
{
src: 'node_modules/le-kit/dist/components/assets/*',
dest: 'le-kit/assets',
},
{
src: 'node_modules/le-kit/src/assets/custom-elements.json',
dest: 'le-kit/assets',
},
],
}),
],
});Add the script tag to your index.html:
<script type="module" src="/le-kit/le-kit.esm.js"></script>Next.js
Next.js serves everything inside the public/ folder as static files, so you can copy the assets there as
part of your install script. Add a postinstall script to your package.json:
{
"scripts": {
"postinstall": "node scripts/copy-le-kit-assets.mjs"
}
}import { cpSync, mkdirSync } from 'node:fs';
const src = new URL('../node_modules/le-kit', import.meta.url).pathname;
const dest = new URL('../public/le-kit', import.meta.url).pathname;
mkdirSync(dest + '/assets', { recursive: true });
// Runtime bundle
cpSync(src + '/dist/le-kit', dest, { recursive: true });
// Icons
cpSync(src + '/dist/components/assets', dest + '/assets', { recursive: true });
// Custom Elements Manifest (admin mode)
cpSync(src + '/src/assets/custom-elements.json', dest + '/assets/custom-elements.json', { recursive: true });
console.log('Le-Kit assets copied to public/le-kit');
Then load the bundle from your root layout (e.g.
app/layout.tsx):
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<script type="module" src="/le-kit/le-kit.esm.js" />
</head>
<body>{children}</body>
</html>
);
}webpack
Use copy-webpack-plugin to copy the assets during the build.
npm install -D copy-webpack-pluginconst CopyPlugin = require('copy-webpack-plugin');
const path = require('path');
const leKitSrc = path.resolve(__dirname, 'node_modules/le-kit');
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: path.join(leKitSrc, 'dist/le-kit'),
to: 'le-kit',
},
{
from: path.join(leKitSrc, 'dist/components/assets'),
to: 'le-kit/assets',
},
{
from: path.join(leKitSrc, 'src/assets/custom-elements.json'),
to: 'le-kit/assets/custom-elements.json',
},
],
}),
],
};Custom asset paths
If you place the assets somewhere other than next to the bundle (for example in a CDN sub-path), you need to tell
Le-Kit where to find them. Call configureLeKit before any component is rendered:
import { configureLeKit } from 'le-kit';
configureLeKit({
// Path prefix used when loading icons
assetBasePath: '/static/le-kit-assets',
// URL of the Custom Elements Manifest (admin mode only)
manifestFile: '/static/le-kit-assets/custom-elements.json',
});
When assetBasePath is set, icons will be fetched from
{assetBasePath}/icons/{name}.json. When it is empty (the default), Stencil's built-in getAssetPath() is used instead, which resolves paths relative to the bundle file — so the default directory layout above works without
any extra configuration.