Astro
Astro is a popular web framework for generating static, server or even hybrid-rendered sites and applications.
Sailhouse can be leveraged in server endpoints, and even directly on pages themselves, via the @sailhouse/client package for JavaScript and TypeScript.
Basic usage
Server endpoints (API Routes)
Astro’s Server Endpoints serve as the base for defining a traditional POST, PUT etc. API handler.
You can utilise the Sailhouse client to handle anything from JSON all the way to form data.
const client = new SailhouseClient(import.meta.env.SAILHOUSE_TOKEN);
export const POST: APIRoute = async ({ request, redirect }) => { const data = await request.formData();
await client.publish("email-submitted", { email: data.get("email"), });
return redirect('/thanks')}Page SSR
Server Side Rendered pages on Astro execute the JavaScript/TypeScript included in the Frontmatter --- section at the top of a .astro page.
This includes access to a Request object via Astro.request, allowing you to read in any POST data sent to the page (via a form submission etc.)
---import { SailhouseClient } from "@sailhouse/client";
let submitted = false;if (Astro.request.method === "POST") { const data = await Astro.request.formData();
const client = new SailhouseClient(import.meta.env.SAILHOUSE_TOKEN); await client.publish("email-submitted", { email: data.get("email"), });
submitted = true;}---
<div> {submitted && <div style={{ marginBottom: 12 }}>Thanks for submitting!</div>} <form method="post"> <input type="email" name="email" /> <button type="submit">Submit</button> </form></div>Middleware
Astro also includes a very flexible middleware API for mutating all requests as they come in before being sent to the specific pages or API routes.
The Sailhouse client can be injected via middleware to make it even easier to utilise across your whole application.
Setting up env.d.ts - TypeScript only
If you’re utilising TypeScript, you’ll want to configure the src/env.d.ts file to include the SailhouseClient type on the request types.
/// <reference types="astro/client" />
declare namespace App { interface Locals { client: import('@sailhouse/client').SailhouseClient }}Injecting the client
To inject the client, we first need to create src/middelware.ts (or .js if you’d like) if it does exist already.
Below is an example focused on just Sailhouse.
import { SailhouseClient } from "@sailhouse/client";import { defineMiddleware } from "astro:middleware";
export const onRequest = defineMiddleware(async ({locals}, next) => { const client = new SailhouseClient(import.meta.env.SAILHOUSE_TOKEN);
locals.client = client;
await next();})Using the client
Now, on every server-side request, Sailhouse is accessible via the locals property.
Server Endpoints
For server endpoints, notice the destructuring of locals to retrieve client in the route arguments.
import type { APIRoute } from "astro";
export const POST: APIRoute = async ({ request, redirect, locals: { client }}) => { const data = await request.formData();
await client.publish("email-submitted", { email: data.get("email"), });
return redirect('/thanks')}Page SSR
For server-rendered pages, notice the reference to Astro.locals.client instead of a freshly instantiated SailhouseClient as above.
---let submitted = false;if (Astro.request.method === "POST") { const data = await Astro.request.formData();
await Astro.locals.client.publish("email-submitted", { email: data.get("email"), });
submitted = true;}---
<div> {submitted && <div style={{ marginBottom: 12 }}>Thanks for submitting!</div>} <form method="post"> <input type="email" name="email" /> <button type="submit">Submit</button> </form></div>