How to embed Svelte apps inside PHP?

Justin's profile pic

Justin Ahinon

Last updated on

Enter your email to get this article emailed to you

Svelte version: 4.2.0

rollup-plugin-svelte version: 7.1.6

GitHub repository:

During my time as a Senior Frontend Engineer at WebDevStudios, we were walking on a lot of headless WordPress projects with custom PHP WordPress themes.

One of them was the new NBA Cares  website. While building this site, we faced situations where we needed some highly interactive sections/components that would be hard to build with PHP or just vanilla JavaScript .

As a Svelte enthusiast, I advocated a lot for trying Svelte for those components .

This blog post is a summary of the approach we used, and more generally, a guide on how to embed Svelte apps inside monolithic PHP apps.

Why adding Svelte to my PHP codebase?

You might be wondering:

  • Why would I add Svelte to my PHP codebase? I can do everything with PHP.

  • What are the benefits of adding Svelte to my PHP codebase?

These are all legitimate questions. Let's try to answer them.

First, from my experience teams / people who go to using Svelte inside PHP codebases have one (or all) of these motivations:

They are in the process of migrating their codebase to a modern JavaScript framework

This is the most common use case I've noticed. The team is in the process of migrating their codebase to a modern JavaScript framework (React, Vue, Svelte, etc.). They want to start using the new framework for new features, but they don't want to rewrite the whole codebase at once . So, the solution is to do it progressively.

Svelte makes this incremental adoption very straightforward by allowing developers to write and bundle Svelte components, and import them as JavaScript modules in their PHP codebase.

Remember, at its core, Svelte is a compiler  that turns your declarative Svelte components into highly performant native JavaScript code.

No need to set up complex systems to handle a frontend framework runtime on your application. Just import the JavaScript code generated by Svelte and you're good to go.

They need some interactivity or state management features that hard to implement with PHP / vanilla JavaScript

Modern JavaScript frameworks like Svelte provide powerful capabilities for building interactive UI components with minimal code . Features like declarative bindings, built-in state management, and reactive directives allow developers to create dynamic interfaces that would require significantly more effort with plain PHP/JS.

For example, implementing complex interactions like drag-and-drop, infinite scroll, or live filtering/searching using vanilla PHP/JS often involves a lot of imperative DOM manipulation and "state juggling" between HTML, JS, and PHP.

With Svelte, the same features can be built in a declarative in a fraction of the code.

State management with global stores/contexts, custom events, lifecycle hooks, etc. also becomes much simpler compared to passing data back and forth between PHP controller logic. This makes it easier to build encapsulated, reusable components with managed internal state.

So for teams that need richer interactivity and state management, adding Svelte components can provide a big productivity boost compared to staying within PHP/JS. The components handle the complex UI code internally, while exposing a simple interface to the rest of the PHP app.

Practical example: building an interactive and filterable blog posts search component inside a PHP WordPress theme

Now that you've seen why you might want to add Svelte to your PHP codebase, let's see how to do it in practice. For this example, we will build a blog posts search component that will be embedded inside a PHP WordPress theme.

The idea is to be able to:

  • Fetch blog posts from the WordPress REST API inside the Svelte component

  • Filter the blog posts by category

  • Filter the blog posts by search query

Here is a demo video of the final result:

You can also check the theme code on GitHub here:

For this example, I'm going to use a "classic" (or PHP) WordPress theme, Twenty Twenty.

In order to not mess up with the theme architecture, I've created a new custom page template named "Svelte Posts Search".

Initially, it's just a replicate of the default  singular.php  of Twenty Twenty that I'll later on update with my custom Svelte component code.


Since it's the compiled JavaScript by Svelte that we are including in our WordPress, we need a tool that will transpile our Svelte code to JavaScrip t.

For that, I like using Rollup. It's a module bundler that allows you to write your code in the latest JavaScript syntax and bundle it for production. It's also very easy to use with Svelte.

I'm also going to use TypeScript as much as possible (in my Svelte components).

I like and highly recommend using Svelte with TypeScript. The experience is really worth it, and the benefits in terms of developer experience and code maintainability are high.

I wrote a blog post about why I like using TypeScript with Svelte and SvelteKit here.

Let's start by installing the needed dependencies:

code loading...

Now, we can go ahead and create our Rollup configuration file:

code loading...

Note that here we are using the  .mjs  extension for the Rollup file. This is because our  package.json  doesn't contain a  "type": "module" .

Here is what's happening in the config:

  • We define the entry point of our Svelte app.

  • We define the output format

  • And we add the necessary plugins

Another nice addition to the project would be a minimal  tsconfig.json  file for proper TypeScript support.

code loading...

We are now ready to start writing Svelte code inside our WordPress theme.

Our first Svelte component

Svelte entry point

As you saw above, our Svelte code is going to be located in the  svelte  folder at the root directory. Inside this folder, we have a  main.ts  entry point.

code loading...

What's happening here is quite simple. We are importing an  App.svelte  component (we'll create this in the next step), and exporting the component, with the target being an element with the id  wp-svelte-search .

Add the target for the Svelte application in the template

This is actually an HTML element that we need to create in the PHP template (the custom WordPress template we created earlier), and on which the Svelte application is going to be hooked.

Here is the full code for the PHP template. Notice that we are creating an empty  div  element with the  wp-svelte-search  ID.

code loading...

Enqueue the compiled JavaScript in our theme

Now, it's time to enqueue the compiled JavaScript in our theme. Firs, let's add the following scripts in our  package.json  to watch and build the JavaScript.

code loading...

We can now update the theme  function.php  to include the script.

Ideally, I would have done that in a WordPress child theme, but, for the sake of keeping this article simple, I will add it directly to the main theme functions.php.

code loading...

Here, we are updating the initial  twentytwenty_register_scripts()  function to enqueue the script, and then, we are using the  script_loader_tag  to load the script as a JavaScript module.

Create the Svelte component

The last step in the process is to create the  App.svelte  component.

code loading...

Quite simple right? Just a  h1  tag with a red font color and a  console.log() .

Fetching data from the WordPress REST API

The first step in creating our blog posts search component is to fetch the blog posts from the WordPress REST API. This is quite simple if you look at the documentation of the WordPress REST API.

code loading...

Since we are using the browser fetch API, we need to make sure our component is mounted before fetching the data. This is why we are using the  onMount  lifecycle hook. Doing that help us in two ways:

Note that I'm casting the response to the WP_Post type that is defined in another file. This is because I'm using TypeScript. If you are using plain JavaScript, you can remove this line.

Once we have the data, we can use it in our component.

code loading...

With this code, we are looping over the  filteredPosts  array and displaying the title and the excerpt of each post.

Searching and filtering the posts

The next step is to add the search and filter functionality to our component. This is also quite simple with Svelte. We need a search input field, and we need to filter the posts array based on what's being typed.

Now, since we will make many operations on the  posts  array, it's a good idea to create another variable that will be reactive to  posts  and on which we will perform the filtering operations; while preserving the initial posts array.

code loading...

A lot of things are happening here, but let's break it down:

  • The search input field is bound to the  searchPosts  function on the  keyup  event.

  • Every time this event is fired, we get the value of the input field, and we filter the  posts  array based on this value.

This will automatically update the markup and display the filtered posts.

Now, this implementation is very simple and works well since the data we are filtering on is already local. In case we need to fetch the data from an external API, we might need to use a more advanced technique like debouncing.

Filtering by category

Now, let's tackle the category filtering. This is a bit more complex than the search filtering because we need to fetch the categories from the WordPress REST API, and then, we need to filter the posts based on the selected category.

Here are the utilities functions that I've used to handle different parts of this:

code loading...

  • getCategoryData()  is a function that fetches a category from the WordPress REST API based on its ID.

  • getUniqueCategoriesFromPosts()  returns an array of unique categories from an array of posts.

  • getCategoryCountInPosts()  returns the number of posts that belong to a specific category.

Notices that here, although I could have directly used the posts array for the last two functions, I'm still passing it as an argument.

This is because I want to make sure that the functions are pure and don't mutate the posts array if they are used somewhere else in the component.

Also, this will make things easier in the future if we need to use these functions in another component.

Let's take a look at the markup for the filter:

code loading...

Let's break down again what we are doing here:

  • We created a reactive  checkedCategoriesIds  array that will hold the IDs of the selected categories.

  • We are using the  checkedCategoriesIds  array to filter the  posts  array and display only the posts that belong to the selected categories. In case no category is selected, we display all the posts.

  • In the markup, we loop over the unique categories and display them as checkboxes. We also display the number of posts that belong to each category.

  • All the checkboxes are bound to the  checkedCategoriesIds  array thanks to Svelte  bind:group  binding.

And that's it! We now have a fully functional blog posts search component that we can embed inside our PHP WordPress theme.


In this post, we explored how to embed interactive Svelte components into a PHP codebase, using a WordPress theme as a practical example.

The key takeaways are:

  • Svelte's compiled output is just JavaScript, which makes it easy to integrate into any backend using simple script tags. No complex integration logic needed.

  • For development, you can use a bundler like Rollup to watch your Svelte code and output browser-ready JS bundles.

  • Svelte components can fetch data from PHP APIs and integrate tightly with the backend, while keeping complex UI code encapsulated.

  • Features like declarative bindings, reactivity, and stores make it simple to build interactive interfaces that would require much more imperative code with PHP/JS.

  • Svelte is a great way to progressively modernize a PHP app, by gradually replacing PHP view code with reusable components.

Overall, adding Svelte allows you to leverage the benefits of a modern web framework incrementally, without needing to rewrite your entire app.

So if you have a PHP app and are looking to enhance the frontend with more interactivity and cleaner code, give Svelte a try! Start small, and you'll soon find places where it can really improve your development experience.

You might also like these blog posts

A lovely bath

How to debounce in Svelte?

Learn how to debounce functions in Svelte to limit how often they run. Implement a debounce utility to rate limit API calls for search boxes and other inputs.

A lovely bath

Headless WordPress with GraphQL and SvelteKit

Want to take your WordPress site to the next level? Learn how to go headless with SvelteKit and GraphQL.

A lovely bath

Top 10 Big Companies Using Svelte

Discover why leading tech giants choose Svelte for their web apps and websites. Learn how Okupter, your Svelte and SvelteKit specialist, can boost your business online.

A lovely bath

Svelte vs SvelteKit: What's the Difference?

Find out what's Svelte, SvelteKit, what is the difference between the two and what you can do with both.