The contact form, booking calendar and booking button are one script tag each — they work on any website. Grab your snippets ready-made from Settings → Embeds in your dashboard, or paste the examples below. Want the pages themselves on your own domain?
frame-ancestors. Add your site under Settings → Embeds → Allowed embed sites, or the browser will block the iframe. If your site ships its own CSP, allow script-src https://snap.webcules.com and frame-src https://snap.webcules.com.The tabs below mount the actual @webcules/snap-react components — the same code the React guide gives you.
Rendered by the published components — unmount/remount the tabs to see the StrictMode-safe lifecycle.
Paste where the widget should appear. No build step, no framework — this is the base form every other guide reduces to.
Contact form
<!-- Snap · contact form -->
<div data-snap-widget="contact"
data-snap-key="YOUR_EMBED_KEY"
data-snap-theme="auto"></div>
<script src="https://snap.webcules.com/embed/loader.js" async></script>Booking calendar with token overrides
<!-- Snap · booking calendar, themed -->
<div data-snap-widget="calendar"
data-snap-key="YOUR_EMBED_KEY"
data-snap-theme="dark"
data-snap-accent="#1e8e3e"
data-snap-radius="16px"></div>
<script src="https://snap.webcules.com/embed/loader.js" async></script>Booking button (opens a modal)
<!-- Snap · booking button -->
<div data-snap-widget="calendar-button"
data-snap-key="YOUR_EMBED_KEY"
data-snap-label="Book a session"></div>
<script src="https://snap.webcules.com/embed/loader.js" async></script>Tokens: data-snap-theme (light / dark / auto), data-snap-accent, data-snap-radius, data-snap-font-family, data-snap-inherit="auto" (samples the surrounding page so the widget blends in). Omitting tokens falls back to your studio brand.
Two ways — the React package, or the zero-dependency script variant.
1a. React package (npm)
npm install @webcules/snap-react// app/booking/page.tsx → components use hooks, so mark the file "use client"
"use client";
import { SnapCalendar } from "@webcules/snap-react";
export default function BookingPage() {
return <SnapCalendar apiKey={process.env.NEXT_PUBLIC_SNAP_KEY!} theme="auto" />;
}1b. next/script variant (no npm dependency)
// app/booking/page.tsx — a Server Component is fine here
import Script from "next/script";
export default function BookingPage() {
return (
<>
<div
data-snap-widget="calendar"
data-snap-key={process.env.NEXT_PUBLIC_SNAP_KEY!}
data-snap-theme="auto"
/>
<Script src="https://snap.webcules.com/embed/loader.js" strategy="afterInteractive" />
</>
);
}StrictMode-safe: the package mounts through window.Snap.mount and destroys on cleanup, so the double-invoked effect in development remounts cleanly.
Works with zero wrapper — but mark the loader is:inline, or Astro will try to bundle the remote script instead of emitting the tag.
---
// src/pages/contact.astro (.env: PUBLIC_SNAP_KEY=…)
const key = import.meta.env.PUBLIC_SNAP_KEY;
---
<div data-snap-widget="contact" data-snap-key={key} data-snap-theme="auto"></div>
<script is:inline src="https://snap.webcules.com/embed/loader.js" async></script>Install
npm install @webcules/snap-reactimport { SnapContactForm, SnapCalendarButton } from "@webcules/snap-react";
function App() {
return (
<>
<SnapContactForm apiKey={import.meta.env.VITE_SNAP_KEY} inherit />
<SnapCalendarButton apiKey={import.meta.env.VITE_SNAP_KEY} label="Book a session" />
</>
);
}SPAs with client-side routing: the components mount/unmount with the route, and the loader script is injected once per document automatically.
Add a Custom HTML block (Gutenberg) or a HTML widget (Classic) where the widget should appear, and paste the snippet.
<!-- Custom HTML block -->
<div data-snap-widget="calendar"
data-snap-key="YOUR_EMBED_KEY"
data-snap-theme="auto"></div>
<script src="https://snap.webcules.com/embed/loader.js" async></script>For site-wide placement, paste the same snippet into your theme template (e.g. page-template.php) or a header/footer-scripts plugin. If your theme strips script tags, use a "custom code" plugin that supports them.
Use each builder's embed block — Squarespace Code Block, Wix HTML iframe / Custom Element, Framer Embed — and paste the snippet.
<div data-snap-widget="calendar-button"
data-snap-key="YOUR_EMBED_KEY"
data-snap-label="Book a session"></div>
<script src="https://snap.webcules.com/embed/loader.js" async></script>Some builders sandbox embed blocks into blank iframes — if the widget doesn't appear, use the builder's site-level code injection (Squarespace: Settings → Advanced → Code Injection; Wix: Settings → Custom Code) with the placeholder div in the page body and the script tag in the footer.