React / Next.js Installation
Connect existing React or Next.js forms to localbot, or install the full localbot form with a site-wide script.
Connect localbot to a React or Next.js site through the current form notification email, or install the full localbot form with a site-wide script.
Start with the current form
If this site already has a working contact form, add the unique localbot email address as another notification recipient first. Keep the current form handler, but make sure its notification email includes the lead's name, phone number, email, message, page URL, and any SMS consent language you already show on the form.
Use the full localbot form when the owner wants a better intake surface on the website instead of relying on a static contact page form.
Existing form time: About 1 minute
Install the full localbot form
The steps below add the floating localbot form globally.
Full form time: About 10 minutes
Next.js (App Router)
Add the form script to your root layout
Open your root layout file (app/layout.tsx) and add the script using next/script:
import Script from "next/script";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<Script
src="https://www.localbot.io/api/widget/YOUR_WIDGET_ID"
strategy="afterInteractive"
/>
</body>
</html>
);
}React (Vite, Create React App, etc.)
Add the form script to index.html
Open your index.html file and add the script before the closing </body> tag:
<script src="https://www.localbot.io/api/widget/YOUR_WIDGET_ID" async></script>
</body>Targeting a specific component
To render the localbot form inside a specific React component, add a target div:
export function ContactSection() {
return (
<section>
<div id="localbot-contact" />
</section>
);
}The localbot script automatically finds #localbot-contact and renders the form inside it.
Verify
Start your dev server and open the page. The localbot form should appear. Submit a test message and check your phone.
Content Security Policy
If your Next.js app sets a Content-Security-Policy header (via next.config.ts or middleware), allow https://www.localbot.io in script-src and connect-src, plus https://challenges.cloudflare.com in script-src and frame-src. Without this, the browser silently blocks the localbot form or its Turnstile challenge.
// next.config.ts
const nextConfig = {
async headers() {
return [
{
source: "/(.*)",
headers: [
{
key: "Content-Security-Policy",
value: [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' https://www.localbot.io https://challenges.cloudflare.com",
"connect-src 'self' https://www.localbot.io",
"frame-src 'self' https://challenges.cloudflare.com",
].join("; "),
},
],
},
];
},
};script-src is required for the localbot form and Turnstile script to load. connect-src is required for form submissions. frame-src allows Turnstile's invisible challenge frame.
Turnstile hostname authorization
The dedicated localbot widget must use Cloudflare Turnstile's Invisible mode and authorize every customer hostname where the form runs. Standard Turnstile widgets support up to 10 hostnames, so maintain the list explicitly. Cloudflare Any Hostname is Enterprise-only. localbot still validates the hostname returned with each challenge.
Troubleshooting
- localbot form doesn't appear in development: The form fetches from
localbot.io. Make sure you have internet access and the ID in the script URL is correct. - localbot script request shows as blocked or returns no response: Check your CSP header. See the "Content Security Policy" section above.
- Hydration warnings: The localbot form injects DOM after React hydration. This is expected and does not affect functionality. Using
#localbot-contactas a target avoids body-level injection.
Last updated: 2026-05-23. Maintained by Benjam Indrenius.