Astro integration
Bookings in an Astro site
Nothing in nisebookings is Astro-specific, and that is the point. The booking form is a web component that talks to the API itself, so a fully static Astro site is enough. Server rendering and server routes are optional: for when you want services rendered on the server, or webhooks in your own project.
Why it fits a static site
-
No backend on your side
The booking form loads from the nisebookings CDN and calls the public API with the site’s public key. Your build stays static: no adapter, no serverless function.
-
Your fonts and colours
The component runs in a shadow DOM and inherits the page’s font. Colours, radius and spacing are CSS custom properties on the element.
-
Server rendering when you want it
On a server-rendered page, fetch services in the frontmatter and render your own markup. Book with a form post or fetch, through the same API the booking form uses.
-
Webhooks next to your code
An Astro server route (`export const POST`) receives signed webhooks and forwards them to a CRM, Slack or a spreadsheet.
Three patterns
Copy, paste, adapt. The public key is in the account settings, next to Allowed websites.
Static page with the booking form
Two lines in any .astro file, no client JavaScript of your own. The fastest path, and it works with output: 'static'.
<script src="https://app.nisebookings.com/widget.js" defer></script>
<nise-booking data-key="YOUR_PUBLIC_KEY"></nise-booking> Services rendered on the server
Fetch the public API in the frontmatter for cards, prices and durations. Keep the booking form for the booking step, or book through the public API directly.
---
// src/pages/book.astro — output: 'server' or 'hybrid'
const res = await fetch('https://app.nisebookings.com/api/public/YOUR_PUBLIC_KEY/services');
const { services } = await res.json();
---
<ul>
{services.map((s) => <li>{s.title} — {s.duration} min — € {s.price}</li>)}
</ul>
<script src="https://app.nisebookings.com/widget.js" defer></script>
<nise-booking data-key="YOUR_PUBLIC_KEY"></nise-booking> A webhook route
Receive booking events in src/pages/api/webhooks.ts, check the signature with the documented verifier, and forward what you need.
// src/pages/api/nisebookings.ts
import type { APIRoute } from 'astro';
export const POST: APIRoute = async ({ request }) => {
const raw = await request.text();
// Verify the signature before trusting it — the webhooks guide has the
// verifier to copy (Standard Webhooks, HMAC-SHA256, raw body).
return new Response(null, { status: 200 });
}; Theming
Set --nb-accent, --nb-radius and the other variables on the element or in your global stylesheet. The component inherits font-family, font-size and colour from the page, so it reads as part of the site, not as an embedded form.
<style>
nise-booking {
--nb-accent: #E8276B;
--nb-radius: 4px;
}
</style> What is tested
What holds and what does not
The runnable example behind this page was checked against a sandbox. The booking form showed the catalogue. The server-rendered page booked a real appointment and handled a slot that was taken in the meantime. The webhook route accepted a correctly signed payload and rejected a wrong one. Not tested: view transitions. On client-side navigation the element is re-created, so try that path before you rely on it. Missing something? Send a mail.
Try it now, no account
curl -s -X POST https://app.nisebookings.com/api/sandbox
# → a 24-hour account with a public key and an API key.
# Mail is captured, payments are fake. Next steps
-
Astro example
A runnable Astro app: the booking form on a static page, your own server-rendered UI and a webhook route.
-
Widget reference
Every attribute, theme variable and event, with the exact embed lines.
-
Public API
Services, slots, prices, bookings and payments, with OpenAPI 3.1.
-
Quickstart
From an empty account to a live booking, step by step.
-
Next.js example
A runnable project with a booking form page, your own UI and a webhook route.
Put bookings on your next site.
Start free and build against a sandbox. Pay once your client takes real bookings.
Free account. All you need is an e-mail address.