Svelteup bundles Svelte components into browser-ready custom elements with Rolldown.
It is built for small, precise embeds: widgets, page fragments, custom elements, and Svelte-powered UI that you can insert into an existing website without moving that website to a full Svelte app stack.
compilerOptions.customElement: true.iife output for classic script embeds.url(...) asset copying with publicPath support.pnpm add -D svelteup
Run the CLI through your package manager:
pnpm exec svelteup --help
Create a Svelte custom element:
<!-- components/counter-app.svelte -->
<svelte:options customElement="counter-app" />
<script>
let count = $state(0);
</script>
<button onclick={() => count += 1}>count {count}</button>
Build it:
svelteup components -o public/dist
Embed it in HTML:
<counter-app></counter-app>
<script type="module" src="./dist/counter-app.js"></script>
Svelteup accepts a JavaScript or TypeScript file, or a directory of first-level Svelte components.
Use a file entry when you want one bundle that imports everything it needs:
svelteup components/index.js -o public/dist
Use a directory entry when you want each first-level .svelte file to become its own browser-ready bundle:
svelteup components -o public/dist
Start the dev server with watch rebuilds and live reload:
svelteup components -d
By default, Svelteup serves public at http://localhost:9527 and writes bundles to public/dist.
svelteup [entry] [options]
| Option | Description |
|---|---|
-o, --outdir |
Set the output directory. Defaults to public/dist. |
-c, --config |
Set the config file path. Defaults to svelteup.config.js. |
--format |
Set the output format: esm or iife. Defaults to esm. |
--global-name |
Set the IIFE global name. Defaults to SvelteupBundle. |
--code-splitting |
Enable ESM code splitting. Defaults to false. |
--public-path |
Set the public URL prefix for emitted assets and snippets. |
--assets-dir |
Set the asset output directory name. Defaults to assets. |
--external |
Mark dependencies as external with a comma-separated list. |
--globals |
Set IIFE external globals as a JSON object. |
--analyze |
Print a bundle dependency breakdown. |
--no-report |
Disable size and embed snippet reporting. |
-d, --dev |
Start development mode with a static file server. |
-w, --watch |
Watch and rebuild without starting the static file server. |
-v, --version |
Print the installed version. |
-h, --help |
Print CLI help. |
Create svelteup.config.js, svelteup.config.mjs, or svelteup.config.ts in your project root. CLI options override config values.
import { defineConfig } from 'svelteup';
export default defineConfig({
entry: 'components/index.js',
outdir: 'public/dist',
format: 'esm',
codeSplitting: false,
publicPath: './dist/',
assetsDir: 'assets',
analyze: false,
report: true,
serveOptions: {
servedir: 'public',
port: 9527,
host: 'localhost',
},
});
| Parameter | Description |
|---|---|
entry |
File or directory entry used when the CLI entry is omitted. |
outdir |
Directory for generated bundles. |
format |
Output format. Use esm or iife. |
globalName |
Global variable name used for iife output. |
codeSplitting |
Enable Rolldown code splitting for ESM output. Defaults to false. |
publicPath |
Public URL prefix used for emitted assets and embed snippets. |
assetsDir |
Directory name for copied CSS url(...) assets. |
external |
Dependencies left outside the bundle. |
globals |
Global variable names for external dependencies in iife output. |
analyze |
Print the largest rendered modules for each output chunk. |
report |
Print size reporting and embed snippets after build. |
compilerOptions |
Options passed to the Svelte compiler. |
preprocess |
Svelte preprocess configuration. |
serveOptions |
Development server options used in development mode. |
onRebuild |
Rebuild hook for development workflows. |
Svelteup sets compilerOptions.customElement to true by default. Set it to false when you want to use Svelte as a client-rendered app without custom elements.
Svelte custom elements can expose attributes and DOM properties through <svelte:options customElement={...}>.
<svelte:options
customElement={{
tag: 'profile-card',
props: {
label: { attribute: 'label', reflect: true, type: 'String' },
},
}}
/>
Host pages can pass children into slots and listen for custom events with standard DOM APIs:
<profile-card label="Brandon">Profile content</profile-card>
<script type="module" src="./dist/profile-card.js"></script>
<script>
document.querySelector('profile-card').addEventListener('confirm', (event) => {
console.log(event.detail);
});
</script>
Use CSS custom properties when a host page needs to theme shadow DOM styles:
button {
color: var(--profile-card-accent, #111827);
}
Svelteup emits ESM by default:
export default defineConfig({
format: 'esm',
});
Use iife when the host page needs a classic script:
export default defineConfig({
format: 'iife',
globalName: 'WidgetBundle',
});
Svelteup keeps code splitting disabled by default so a custom element can be embedded as one predictable file. Enable it for ESM builds that use dynamic imports or shared chunks:
export default defineConfig({
entry: 'components/index.js',
format: 'esm',
codeSplitting: true,
});
Code splitting is not available for iife output because split chunks load through native ESM imports.
See examples/code-splitting for a dynamic import example.
Production builds print:
.svelte files.Disable this output with report: false or --no-report.
Use analyze: true or --analyze to print the largest rendered modules in each output chunk.
Use external when the host page already provides a dependency. For iife output, pair external modules with globals:
export default defineConfig({
entry: 'components/index.js',
format: 'iife',
globalName: 'WidgetBundle',
external: ['host-sdk'],
globals: {
'host-sdk': 'HostSDK',
},
});
Svelteup copies relative CSS url(...) assets referenced from Svelte component styles into assetsDir, then rewrites the CSS URL with publicPath.
export default defineConfig({
outdir: 'public/dist',
publicPath: '/dist/',
assetsDir: 'assets',
});
Browser target policy: Svelteup emits modern browser JavaScript. It does not transpile syntax for legacy browsers. Use modern ESM-capable browsers for the default esm output, and use iife when the host page requires a classic script.
import svelteup from 'svelteup';
svelteup('components/index.js', {
outdir: 'public/dist',
serveOptions: {
servedir: 'public',
},
});
Run one of the example projects locally:
cd examples/custom-element
pnpm exec svelteup -d
Available examples:
Svelteup keeps first-party starter templates in this repository under templates/.
They are listed in package.json through createConfig.templates, so the same entries can be exposed from a Vite+ @org/create package.
vp create @your-org:svelteup-starter
vp create @your-org:svelteup-revealjs
vp create @your-org:svelteup-chrome-extension
Available templates:
MIT @brandonxiang