Available since v0.1.0
Astro
StableAstro is a component-based SSR framework with "islands architecture" — most of the page is static HTML, interactive components are opt-in via client:* directives and hydrate client-side. fs-* attributes work on both static HTML and hydrated islands.
Install
Load the agent in your layout (src/layouts/Layout.astro):
---
const releaseLabel = import.meta.env.RELEASE_LABEL;
---
<html>
<head>
<script src="/faultsense-agent.min.js" defer></script>
<script is:inline define:vars={{ releaseLabel }}>
document.addEventListener('DOMContentLoaded', () => {
Faultsense.init({
releaseLabel: releaseLabel,
collectorURL: '/events',
apiKey: 'fs_secret_...',
});
});
</script>
</head>
<body>
<slot />
</body>
</html>
is:inline + define:vars is Astro's CSP-friendly way to pass build-time values into an inline script without string interpolation.
Static HTML pages
Non-island pages are plain SSR HTML. fs-* attributes work without any client-side JS framework:
---
// src/pages/contact.astro
---
<Layout>
<form
fs-assert="contact/submit"
fs-trigger="submit"
fs-assert-mpa="true"
fs-assert-visible=".success">
<input type="email" name="email" required />
<button type="submit">Send</button>
</form>
</Layout>
MPA mode is the right choice here — Astro's default behavior for forms is a full page navigation.
Hydration islands
Islands are components that hydrate client-side via client:load, client:idle, client:visible, or client:only. Each island is a standalone React / Vue / Svelte / Solid / Preact component.
During hydration, the island's root element's identity is preserved. The server-rendered HTML is the starting state; the client framework takes over and patches attributes / children as state changes. fs-trigger="mount" does NOT re-fire on hydration — the element is already in the DOM.
For "assert something is true once hydrated," use fs-trigger="invariant" or fs-assert-updated depending on whether you want continuous monitoring or a one-shot check at the hydration moment.
---
import Counter from '../components/Counter.jsx';
---
<Counter client:load
fs-assert="home/counter-hydrated"
fs-trigger="invariant"
fs-assert-visible=".counter-ready" />
Note: fs-* attributes passed to a framework component reach the DOM only if the component forwards props. For React components, see React notes.
Framework mix
Astro lets you mix React, Vue, Svelte, Solid, and Preact islands in the same site. The framework-specific notes for each apply to the islands that use them:
- React — the boolean attribute trap, TypeScript augmentation
- Vue —
inheritAttrs - Svelte —
$$restPropspass-through - Solid — JSX binding
Gotchas
- CSP and inline scripts. Astro supports
is:inline+define:varsfor build-time values without string interpolation. Prefer external scripts where possible; the<script>tag without a directive is bundled and hashed, which is CSP-friendly. client:onlyislands skip SSR entirely and render only on the client. Elements inside them don't exist until hydration — usefs-assert-addedorfs-trigger="mount"for child elements.- Image optimization. Astro's built-in
<Image>component generates picture/source markup.fs-assert-loadedworks on the eventual<img>element but not on the<picture>wrapper. - Partial hydration + assertions in
<script>tags. Inline scripts inside.astrofiles run once at page load, before island hydration. Don't reference island state from inline scripts.
See also
- Frameworks index
- React notes — React islands
- Vue notes — Vue islands
- Svelte notes — Svelte islands