Svelte Islands in Astro

Use Svelte for small interactive regions inside mostly static Astro pages.

Svelte works well as an Astro island when a page is mostly static but one region needs local browser state. Astro can build the page and pass plain data down. Svelte can handle the interaction.

A file explorer is a good example:

  • Astro builds the tree
  • Svelte stores the open folders
  • folder and note links remain normal anchors

Props

Svelte 5 reads component inputs with $props.1

<script lang="ts">
  type Props = {
    currentPath: string;
    nodes: SidebarNode[];
  };

  let { currentPath, nodes }: Props = $props();
</script>

Keep island props serializable. If a component needs a smaller view model, prepare it before hydration or derive it inside the component.

State

Use $state for state the browser owns, such as expanded folders.2

<script lang="ts">
  let openPaths = $state<string[]>([]);

  function toggle(path: string) {
    openPaths = openPaths.includes(path)
      ? openPaths.filter((item) => item !== path)
      : [...openPaths, path];
  }
</script>

For Set and Map, use the reactive built-ins from svelte/reactivity or reassign a new collection after each change.2

Derived Values

Use $derived when a value comes from props or state.3

<script lang="ts">
  let { currentPath, nodes }: Props = $props();
  let activeBranches = $derived(nodes.filter((node) => currentPath.startsWith(node.path)));
</script>

Use $effect for browser effects: DOM measurement, timers, subscriptions, or third-party libraries.4 Do not use it to copy one piece of state into another if a derived value would work.

Recursive Components

Svelte 5 deprecates <svelte:self>. Import the component and render it by name.

<script lang="ts">
  import SidebarTree from "$components/SidebarTree.svelte";
</script>

{#if node.kind === "folder"}
  <SidebarTree nodes={node.children} currentPath={currentPath} />
{/if}

That pattern works for file explorers, nested comments, outlines, and menus.

Footnotes

  1. Svelte, “$props”, Svelte documentation, https://svelte.dev/docs/svelte/$props

  2. Svelte, “$state”, Svelte documentation, https://svelte.dev/docs/svelte/$state 2

  3. Svelte, “$derived”, Svelte documentation, https://svelte.dev/docs/svelte/$derived

  4. Svelte, “$effect”, Svelte documentation, https://svelte.dev/docs/svelte/$effect