Published on March 25, 2026
Updated on March 25, 2026
Creating a Web Component with SvelteKit: Complete Step-by-Step Guide
Create a Web Component with SvelteKit
In this article, we will see how to create a Web Component with SvelteKit, compile it, and then easily integrate it into any project: WordPress, Shopify, Next.js, or even vanilla JavaScript.
Enable advertising cookies to access this article without blurring.
Create a SvelteKit project for a Web Component
To create a Web Component with SvelteKit, start by initializing a new project:
npx sv create example-webcomponent
cd example-webcomponent
npm run dev
Project Configuration
During the installation, select the following options:
- Minimal SvelteKit
- TypeScript
- Prettier and ESLint (recommended)
- npm
Run the project locally
Once the installation is complete, open your browser at the following address:
If the page displays correctly, your SvelteKit project is ready to be used to create a Web Component.
Enable advertising cookies to access this article without blurring.
Install SCSS in SvelteKit
To use SCSS in your SvelteKit project, you need to install the Sass compiler as a development dependency:
npm install -D sass-embedded
Once installed, SvelteKit will automatically detect SCSS in your .svelte files through the <style lang="scss"> tags.
Enable advertising cookies to access this article without blurring.
Create a Web Component with SvelteKit
We will now create our first Web Component with SvelteKit. To do this, create a file in the src/lib folder:
touch src/lib/my-web-component.svelte
Then add the following code:
<svelte:options customElement="my-web-component" />
<script lang="ts">
</script>
<p>Hello World</p>
<style lang="scss">
p {
color: red;
}
</style>
👉 The customElement="my-web-component" attribute defines the name of your Web Component. This name must contain a hyphen (e.g., my-component) to be valid in HTML.
Enable advertising cookies to access this article without blurring.
Configure SvelteKit for Web Components
To enable the creation of Web Components with SvelteKit, you need to modify the svelte.config.js file and enable the customElement option.
Add the following configuration:
compilerOptions: {
customElement: true
}
Here is a complete example of the configuration:
import adapter from '@sveltejs/adapter-static';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter()
},
vitePlugin: {
dynamicCompileOptions: ({ filename }) =>
filename.includes('node_modules') ? undefined : { runes: true }
},
compilerOptions: {
customElement: true
}
};
export default config;
👉 The customElement: true option allows SvelteKit to compile your components into native Web Components that can be used in any environment.
Enable advertising cookies to access this article without blurring.
Configure the Web Component build with Vite
To generate a reusable Web Component, you need to configure a specific build with Vite. This allows you to export your component as a JavaScript file that can be used in any project.
Create a dedicated configuration file:
touch vite.config.webcomponent.js
Add the following configuration:
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { name, version } from './package.json';
export default defineConfig({
plugins: [svelte()],
publicDir: 'playground',
build: {
lib: {
entry: './src/lib/my-web-component.svelte',
fileName: `${name}-${version}`,
name,
formats: ['es']
},
outDir: 'static/webcomponent',
minify: 'esbuild'
}
});
Add the build script
Add the following script to your package.json file:
"build:wc": "vite build -c vite.config.webcomponent.js"
You can then generate your Web Component with the command:
npm run build:wcEnable advertising cookies to access this article without blurring.
Testing the Web Component in SvelteKit
Once the build is generated, you can test your Web Component directly in your SvelteKit project.
Importing the script
In the +page.svelte file, add the generated script in the <svelte:head> tag:
<svelte:head>
<script type="module" src="/webcomponent/example-webcomponent-0.0.1.js"></script>
</svelte:head>
Using the Web Component
Then add your component in the template:
<my-web-component></my-web-component>
Complete example
<svelte:head>
<script type="module" src="/webcomponent/example-webcomponent-0.0.1.js"></script>
</svelte:head>
<h1>Welcome to SvelteKit</h1>
<p>
Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation
</p>
<my-web-component></my-web-component>
Running the project
Run the following commands:
npm run build:wc
npm run dev
If everything is correctly configured, your Web Component should appear on the page.
Enable advertising cookies to access this article without blurring.
Adding Properties (props) to a SvelteKit Web Component
You can make your Web Component dynamic by passing properties (props) to it.
Defining a prop in the component
In your file my-web-component.svelte:
let { name = 'World' } = $props();
Using the prop in the template
<p>Hello {name}</p>
Complete component
<svelte:options customElement="my-web-component" />
<script lang="ts">
let { name = 'World' } = $props();
</script>
<p>Hello {name}</p>
<style lang="scss">
p {
color: red;
}
</style>
Using the prop in the HTML
You can now pass a value directly from the HTML:
<my-web-component name="Bryan"></my-web-component>
👉 The displayed text will be: Hello Bryan
Enable advertising cookies to access this article without blurring.
Expose JavaScript Methods (API) in a Web Component
You can expose JavaScript methods to interact with your Web Component from the outside (JavaScript, framework, or HTML).
In this example, we will create a getter and a setter to manipulate the property name.
Create the Methods
const getName = (): string => {
return name;
};
const setName = (newName: string) => {
name = newName;
};
Expose the Methods via the Web Component
Use $host() to attach the methods to the DOM element:
$effect(() => {
const host = $host();
Object.assign(host, {
getName,
setName
});
});
Complete Component
<svelte:options customElement="my-web-component" />
<script lang="ts">
let { name = 'World' } = $props();
const getName = (): string => {
return name;
};
const setName = (newName: string) => {
name = newName;
};
$effect(() => {
const host = $host();
Object.assign(host, {
getName,
setName
});
});
</script>
<p>Hello {name}</p>
<style lang="scss">
p {
color: red;
}
</style>
Use the Methods from JavaScript
You can now interact with your Web Component from an external script:
const el = document.querySelector('my-web-component');
// Change the value
el.setName('Bryan');
// Retrieve the value
console.log(el.getName());
👉 This approach allows you to create a true JavaScript API for your Web Component.
Enable advertising cookies to access this article without blurring.
Interacting with a Web Component from SvelteKit
You can interact directly with your Web Component from SvelteKit by accessing its methods via a JavaScript reference.
Declaring a reference to the component
let wc: HTMLElement;
Binding the Web Component
Use bind:this to retrieve a reference to the component:
<my-web-component bind:this={wc} name="User"></my-web-component>
Adding TypeScript typing (recommended)
To avoid errors in your IDE, you can type the exposed methods:
let wc: HTMLElement & {
getName: () => string;
setName: (newName: string) => void;
};
Interacting with the component
You can then call the methods in the onMount lifecycle:
import { onMount } from 'svelte';
onMount(() => {
console.log('Current Name:', wc.getName());
setTimeout(() => {
console.log('== Change Name ==');
wc.setName('Admin');
console.log('Current Name:', wc.getName());
}, 1000);
});
Complete example
<script lang="ts">
import { onMount } from 'svelte';
let wc: HTMLElement & {
getName: () => string;
setName: (newName: string) => void;
};
onMount(() => {
console.log('Current Name:', wc.getName());
setTimeout(() => {
console.log('== Change Name ==');
wc.setName('Admin');
console.log('Current Name:', wc.getName());
}, 1000);
});
</script>
<svelte:head>
<script type="module" src="/webcomponent/example-webcomponent-0.0.1.js"></script>
</svelte:head>
<h1>Welcome to SvelteKit</h1>
<p>
Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation
</p>
<my-web-component bind:this={wc} name="User"></my-web-component>
Output in the console
Current Name: User
== Change Name ==
Current Name: Admin
👉 The Web Component is updated dynamically, and the changes are visible both in the DOM and in the console.
Enable advertising cookies to access this article without blurring.
Using Slots in a SvelteKit Web Component
Slots allow you to inject HTML content from outside into your Web Component. This is essential for making your component flexible and reusable.
Adding a Slot to the Component
In your my-web-component.svelte file, simply add:
<slot />
Modifying the Template
For example, replace:
<p>Hello {name}</p>
With:
<p>Before Hello {name}</p>
<slot />
<p>After Hello {name}</p>
Full Component
<svelte:options customElement="my-web-component" />
<script lang="ts">
let { name = 'World' } = $props();
const getName = (): string => {
return name;
};
const setName = (newName: string) => {
name = newName;
};
$effect(() => {
const host = $host();
Object.assign(host, {
getName,
setName
});
});
</script>
<p>Before Hello {name}</p>
<slot />
<p>After Hello {name}</p>
<style lang="scss">
p {
color: red;
}
</style>
Passing Content from the SvelteKit Page
You can now inject content directly into your Web Component:
<my-web-component bind:this={wc} name="User">
<p>New content</p>
</my-web-component>
Complete Example in SvelteKit
<script lang="ts">
import { onMount } from 'svelte';
let wc: HTMLElement & {
getName: () => string;
setName: (newName: string) => void;
};
onMount(() => {
console.log('Current Name:', wc.getName());
setTimeout(() => {
console.log('== Change Name ==');
wc.setName('Admin');
console.log('Current Name:', wc.getName());
}, 1000);
});
</script>
<svelte:head>
<script type="module" src="/webcomponent/example-webcomponent-0.0.1.js"></script>
</svelte:head>
<h1>Welcome to SvelteKit</h1>
<p>
Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation
</p>
<my-web-component bind:this={wc} name="User">
<p>New content</p>
</my-web-component>
👉 The content passed between the tags of the Web Component will be injected at the location of the <slot />.
Enable advertising cookies to access this article without blurring.
Adding an Image in a SvelteKit Web Component
To integrate an image into a Web Component with SvelteKit, you cannot directly use the static folder. You need to import the image as a module so that it is correctly included in the build.
Importing an Image
In your component my-web-component.svelte:
import logo from './assets/favicon.svg';
Using the Image in the Template
<img src={logo} alt="SvelteKit Logo" />
Complete Component
<svelte:options customElement="my-web-component" />
<script lang="ts">
import logo from './assets/favicon.svg';
let { name = 'World' } = $props();
const getName = (): string => {
return name;
};
const setName = (newName: string) => {
name = newName;
};
$effect(() => {
const host = $host();
Object.assign(host, {
getName,
setName
});
});
</script>
<img src={logo} alt="SvelteKit Logo" />
<p>Before Hello {name}</p>
<slot />
<p>After Hello {name}</p>
<style lang="scss">
p {
color: red;
}
</style>
👉 The image will be automatically optimized and included in the final bundle of the Web Component.
Enable advertising cookies to access this article without blurring.
Listening to Events from a Web Component in SvelteKit
To communicate from a Web Component to your application, you can emit custom events (CustomEvent) and listen to them on the client side.
Creating an Event in the Component
Add a button and a function in your component:
<button on:click={handleClick}>Test</button>
const handleClick = () => {
const event = new CustomEvent('test', {
detail: {
name
}
});
$host().dispatchEvent(event);
};
Creating an API to Listen for Events
To simplify event listening, you can expose an on method:
const on = (event: string, callback: Function) => {
$host().addEventListener(event, (e: any) => callback(e.detail));
};
Exposing the Method
$effect(() => {
const host = $host();
Object.assign(host, {
getName,
setName,
on
});
});
Updating the Typing on the SvelteKit Side
let wc: HTMLElement & {
getName: () => string;
setName: (newName: string) => void;
on: (event: string, callback: Function) => void;
};
Listening to the Event on the Page
wc.on('test', (detail: { name: string }) => {
console.log(detail);
});
Complete Example on the SvelteKit Side
<script lang="ts">
import { onMount } from 'svelte';
let wc: HTMLElement & {
getName: () => string;
setName: (newName: string) => void;
on: (event: string, callback: Function) => void;
};
onMount(() => {
wc.on('test', (detail: { name: string }) => {
console.log(detail);
});
});
</script>
<svelte:head>
<script type="module" src="/webcomponent/example-webcomponent-0.0.1.js"></script>
</svelte:head>
<my-web-component bind:this={wc} name="Admin"></my-web-component>
Result
{ name: 'Admin' }
👉 This approach allows you to communicate your Web Component with any application via a simple and efficient event-driven API.
Enable advertising cookies to access this article without blurring.
Conclusion
You now know how to create a Web Component with SvelteKit, build it with Vite, and integrate it into any project.
- Create a Web Component with SvelteKit
- Set up and build with Vite
- Integrate it into any environment (HTML, React, WordPress…)
- Manage props, methods, slots, and events
👉 Web Components are a powerful solution for creating reusable widgets, whether for a SaaS, an embedded script, or multi-platform plugins.
Thanks to SvelteKit, you can create performant, lightweight components that are completely independent of the client-side framework used.
🚀 You can now create your own widgets and integrate them everywhere: landing pages, CMS, web applications, or client projects.
Enable advertising cookies to access this article without blurring.
Go Further
Do you want to create a custom Web Component for your project or business?
I offer personalized solutions to develop high-performing widgets that can be integrated on any platform (WordPress, Shopify, SaaS…).