Skip to content

Astro

Use StateLoom for shared state across framework islands in an Astro project.

How It Works

Astro renders static HTML by default and hydrates interactive "islands" using React, Vue, Solid, Svelte, or other frameworks. StateLoom provides shared state across these islands through its core signals and paradigm adapters.

Prerequisites

  • Astro 3+
  • Node.js 18+
  • One or more UI framework integrations (React, Vue, Solid, Svelte)

Installation

bash
pnpm add @stateloom/core @stateloom/store
bash
npm install @stateloom/core @stateloom/store
bash
yarn add @stateloom/core @stateloom/store

Add the framework adapter for each island framework you use:

bash
# Example: React + Vue islands
pnpm add @stateloom/react @stateloom/vue

Basic Pattern

Define Shared State

Create state modules that all islands import:

typescript
// src/state/counter.ts
import { signal, computed } from '@stateloom/core';

export const count = signal(0);
export const doubled = computed(() => count.get() * 2);

Use in React Islands

tsx
// src/components/ReactCounter.tsx
import { useSignal } from '@stateloom/react';
import { count, doubled } from '../state/counter';

export function ReactCounter() {
  const value = useSignal(count);
  const double = useSignal(doubled);

  return (
    <div>
      <p>
        React: {value} (doubled: {double})
      </p>
      <button onClick={() => count.set(count.get() + 1)}>+</button>
    </div>
  );
}

Use in Vue Islands

vue
<!-- src/components/VueCounter.vue -->
<script setup lang="ts">
import { useSignal } from '@stateloom/vue';
import { count, doubled } from '../state/counter';

const countRef = useSignal(count);
const doubledRef = useSignal(doubled);
</script>

<template>
  <div>
    <p>Vue: {{ countRef }} (doubled: {{ doubledRef }})</p>
    <button @click="count.set(count.get() + 1)">+</button>
  </div>
</template>

Mount in Astro Page

astro
---
// src/pages/index.astro
import { ReactCounter } from '../components/ReactCounter';
import VueCounter from '../components/VueCounter.vue';
---

<h1>Cross-Framework State</h1>
<ReactCounter client:visible />
<VueCounter client:visible />

Both islands share the same count signal. Incrementing in one island updates the other.

Hydration Directives

Use client:visible or client:load on islands that use StateLoom state. Without a client: directive, the component renders as static HTML and hooks do not run.

Full Guide Coming Soon

A complete Astro example app is under development. For now, use the framework-specific guides for detailed integration patterns:

Next Steps