Embed Widget
All plansAdd interactive step-by-step wizards to any page with a single line of code. No build step, no dependencies, no framework lock-in.
Interactive firstrun guide available
Step-by-step with copy-to-clipboard and progress tracking.
HTML
Paste this anywhere in your HTML. The widget renders a button right where the tag is placed.
<script
src="https://firstrun.dev/embed.js"
data-wizard="your-wizard-slug"
></script>Replace your-wizard-slug with your slug. Find it in the URL when viewing a wizard: firstrun.dev/w/{slug}, or click Embed on the wizard detail page to get the snippet pre-filled.
With all options
<script
src="https://firstrun.dev/embed.js"
data-wizard="my-setup-guide"
data-theme="dark"
data-button-text="Get started"
></script>React, Next.js & Vue
Frameworks strip raw <script> tags from JSX. Instead, load embed.js once and use a <div> marker wherever you want a wizard.
Next.js
import Script from "next/script";
export default function DocsPage() {
return (
<div>
<h1>Getting Started</h1>
{/* Wizard renders here */}
<div data-firstrun="your-wizard-slug" />
{/* Load embed.js once per page */}
<Script
src="https://firstrun.dev/embed.js"
strategy="lazyOnload"
/>
</div>
);
}React (Vite, CRA)
import { useEffect } from "react";
function DocsPage() {
useEffect(() => {
const script = document.createElement("script");
script.src = "https://firstrun.dev/embed.js";
document.body.appendChild(script);
return () => script.remove();
}, []);
return (
<div>
<h1>Getting Started</h1>
<div data-firstrun="your-wizard-slug" />
</div>
);
}Vue
<template>
<div>
<h1>Getting Started</h1>
<div data-firstrun="your-wizard-slug" />
</div>
</template>
<script setup>
import { onMounted } from "vue";
onMounted(() => {
const s = document.createElement("script");
s.src = "https://firstrun.dev/embed.js";
document.body.appendChild(s);
});
</script>You can place multiple data-firstrun divs on the same page — the script picks them all up automatically.
README & Markdown
GitHub and most markdown renderers don't allow scripts or iframes. Use a linked badge instead:
[](https://firstrun.dev/w/your-slug)Replace your-slug with your wizard's slug. Here's what the badge looks like:
Clicking the badge takes users directly to the full interactive wizard on Firstrun.
Attributes
| Attribute | Required | Description |
|---|---|---|
data-wizard | Yes * | Wizard slug. Use on the <script> tag for HTML embeds. |
data-firstrun | Yes * | Wizard slug. Use on a <div> marker for framework embeds (React, Next.js, Vue). |
data-theme | No | "light", "dark", or "auto" (default). Controls the trigger button appearance. The wizard inside the modal follows the user's system preference. |
data-button-text | No | Custom button label. Default: Follow the wizard |
* Use data-wizard on script tags, data-firstrun on div markers. Pick one approach per embed.
How It Works
Full wizard experience
The embed opens the same wizard page your users see on Firstrun — environment detection, step feedback, progress bar, copy-to-clipboard, hints, and verification blocks all work.
CSS Isolation
The trigger button renders inside a Shadow DOM container. Your styles never affect it, its styles never affect your page. The wizard itself loads in an iframe.
No cookies or localStorage
Nothing is persisted to the user's browser by the embed script itself. No cookies, no tracking across page loads.
Zero API calls
The embed script makes no cross-origin API requests. It renders a button and opens an iframe — no CORS configuration needed.
Content Security Policy
Most sites work out of the box. If your site has a strict CSP, add these to your headers:
script-src https://firstrun.dev;
frame-src https://firstrun.dev;script-src allows loading embed.js. frame-src allows the wizard iframe.