Your Astro page stays server-rendered. A small client script mounts the interactive Fillo form into one element.
Install the renderer
bash
npm install @usefillo/domAdd the Astro component
astro
---
import "@usefillo/dom/styles.css";
const { formId = "your-published-form-id" } = Astro.props;
---
<section aria-labelledby="feedback-title">
<h2 id="feedback-title">Product feedback</h2>
<div id="fillo-feedback" data-form-id={formId}></div>
</section>
<script>
import { renderForm } from "@usefillo/dom";
const root = document.querySelector<HTMLElement>("#fillo-feedback");
if (root) {
renderForm(root, {
formId: root.dataset.formId!,
onSubmitted: (responseId) => console.info("Fillo response", responseId),
});
}
</script>If a page has more than one instance, give each a unique element ID. With Astro view transitions, destroy the renderer before the old page leaves and mount again after the new one loads.
Keep secrets out of client scripts
A published form ID is safe in page HTML and doesn't need a key. Ship a pk_ publishable key only when code-defined sync requires it. Private API, identity, webhook, and storage secrets never belong in Astro client scripts.
Try it
Start with a prompt and your coding agent builds the first form, staged for your review — or open the editor.
Related
- Contact example: See the native renderer states before mounting it in Astro.
- Embed quickstart: Compare DOM, web component, and standalone setup.
- Security: Keep each credential on the correct side of the client boundary.
- Styling: Blend the native form into an Astro design system.