3D illustration representing the development of a Web Component with SvelteKit, including a code interface, UI components, and development tools in a modern environment.

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:

http://localhost:5173/

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:wc

Enable 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…).

Profile picture of Bryan Ledda, web and mobile developer specialized in iOS, SvelteKit, and artificial intelligence.

Article written by Bryan Ledda – Web & Mobile Developer

We use cookies to enhance your experience, analyze traffic, and secure the site with Google reCAPTCHA.
You can accept all cookies or manage your preferences.

Learn more about our The key to this text is 'point'.

Your cookie preferences

You can enable or disable each category:

  • Security

  • Analytics

  • Advertising

Privacy Policy

We attach great importance to the protection of your personal data. This policy explains what data we collect, why and how we use it, as well as your rights regarding this data.

  • Collected data

    • Functionality and security cookies: necessary to secure the site (reCAPTCHA).

    • Analytics cookies: used to measure audience and improve the site (Google Analytics).

    • Technical data: IP address, browser type, pages visited, duration of visit.

  • Purpose

    The collected data allows us to:

    • Ensure site security and prevent abuse (reCAPTCHA).

    • Analyze and improve user experience (Google Analytics).

  • Legal basis

    • Mandatory cookies: necessary for the site's operation.

    • Analytics cookies: subject to your explicit consent.

  • Data sharing We do not share your data with third parties except for providers necessary for operation or analysis (e.g., Google).

  • Retention period The data collected through cookies are retained for the maximum duration allowed by the provider (e.g., Google Analytics 14 months).

  • Your rights

    You can at any time:

    • Refuse or withdraw your consent to analytical cookies..

    • Access, rectify, or delete your personal data by contacting us.

  • Contact

    For any questions regarding your data:

    contact@bryanledda.fr