Astro and UI Frameworks
Learning objectives
- You know that Astro is an UI agnostic framework.
- You know how to use Svelte with Astro.
- You know how to use Astro's guidelines for directing how UI components are loaded.
- You know how to manage state across different UI libraries.
Astro is an UI agnostic framework, which allows using a variety of UI libraries and frameworks as a part of the web application.
See also Astro's documentation on UI Framework Components.
Adding a UI framework to the application requires adding an integration to the project. Adding an UI integration to the Astro project is straightforward. For example, for Svelte, we need add the Astro Svelte integration to our project.
Adding Svelte to Astro
To add Svelte to Astro, we run the command npx astro add svelte
in the root folder of the project. The command asks whether we wish to continue, and asks whether Astro should be configured to use Svelte. We answer yes
to both.
npx astro add svelte
✔ Resolving packages...
Astro will run the following command:
If you skip this step, you can always run it yourself later
╭──────────────────────────────────────────────────────────╮
│ npm install @astrojs/svelte astro@^2.0.4 svelte@^3.54.0 │
╰──────────────────────────────────────────────────────────╯
✔ Continue?
yes
✔ Installing dependencies...
Astro will make the following changes to your config file:
╭ astro.config.mjs ─────────────────────────────╮
│ import { defineConfig } from 'astro/config'; │
│ │
│ // https://astro.build/config │
│ import svelte from "@astrojs/svelte"; │
│ │
│ // https://astro.build/config │
│ export default defineConfig({ │
│ output: 'server', │
│ integrations: [svelte()] │
│ }); │
╰───────────────────────────────────────────────╯
✔ Continue?
yes
success Added the following integration to your project:
- @astrojs/svelte
Now, we can use Svelte components in our project.
Loading components
Svelte components are used the same way as Astro components: they are imported into use and added to the site. Create a component called Hello.svelte
to the components
folder under src
and place the following code into it.
<p>Hello Svelte!</p>
Now, adjust the index.astro
in the pages
folder to load the Svelte component into use and add it to the site. After the modification, the index.astro
file should look as follows.
---
export const prerender = true;
import Layout from "../layouts/Layout.astro";
import Hello from "../components/Hello.svelte";
---
<Layout>
<Hello />
</Layout>
When you access the site, the content shown should be similar to Figure 1, and you should see the content from Hello.svelte
shown on the page.

Islands architecture and controlling component hydration
Astro uses the Islands architecture -- interactive components in static websites -- where the interactive components are rendered separately to the static content. By default, Astro renders components statically on the server and adds them to the page, also dropping JavaScript during the process. To illustrate this, modify the Hello.svelte
as follows.
<script>
alert("Hello world");
</script>
<p>Hello Svelte!</p>
When you open up the browser and look at the page with the Svelte component, you notice that no alert dialog is shown, even though one could expect that the alert dialog would pop up. The purpose of this is to minimize the amount of unnecessary JavaScript sent to the client.
Astro features a handful of directives that can be used to control how and when the component is shown to the client (i.e. UI component hydration). These directives include client:load
, client:idle
, client:visible
, and client:only
.
Add the client:load
directive to the Hello
component in the index.astro
and save the file. After saving the file, the contents of index.astro
should be as follows.
---
export const prerender = true;
import Layout from "../layouts/Layout.astro";
import Hello from "../components/Hello.svelte";
---
<Layout>
<Hello client:load />
</Layout>
Now, when you reload the page, you'll see an alert dialog with the message "Hello world!". This is also shown in Figure 2.

While the client:load
directive instructs that the component should be loaded and hydrated immediately on page load, the other directives behave as follows:
The directive
client:idle
instructs to load the component when the browser has loaded the page and processed JavaScript on it, calling for low-priority content to be process by invoking the requestIdleCallback function.The directive
client:visible
instructs to load the component only when the component is visible -- i.e., if it is not in the viewport (it is, for example, at the end of the page), the component is loaded only when the user scrolls to it.The directive
client:only
instructs to not render the component on the server and to load and hydrate it on the client. As Astro's documentation highlights, theclient:only
directive needs to be passed the framework as a value. This provides Astro information on which libraries related to the component should be sent to the client.
Following these, if we adjust the index.page
so that the Hello
component uses the directive client:visible
, and add plenty of page breaks before the component, we can see that the page loads but the alert dialog is not shown.
---
export const prerender = true;
import Layout from "../layouts/Layout.astro";
import Hello from "../components/Hello.svelte";
---
<Layout>
<p>plenty of lines</p>
<p>(copy and paste dozens of these before the Hello component)</p>
<p>plenty of lines</p>
<Hello client:visible />
</Layout>
When scrolling down the page, the alert window pops once we reach the Hello
component, as shown in the Figure 3 belowe.

The directives can be used to reduce traffic and improve the initial page load experience.
Managing state
With multiple UI frameworks, one will end up in a situation where framework-specific approaches for state management do not work across the board. Astro recommends the use of Nano Stores for managing client-side state.
As we are not looking into frameworks beyond Svelte, we can continue using Svelte stores for state management.