How to Embed Forms in Next.js and React Applications via Clean Script Embeds
How to Embed Forms in Next.js and React Applications via Clean Script Embeds
When building modern web applications with Next.js (App Router) and React: Embedding an external form widget often leads to frontend bugs:
- React SSR Hydration mismatch errors.
- Unwanted scrollbar flickering.
- Layout shift (CLS) penalties when iframes load asynchronously.
- Broken responsive viewports.
Here is the clean, production-ready React component implementation for embedding forms cleanly in Next.js without hydration errors or layout bugs.
The Production Next.js Form Component
Create a reusable component at src/components/forms/EmbeddedForm.tsx:
'use client';
import React, { useState, useEffect } from 'react';
interface EmbeddedFormProps {
formSlug: string;
minHeight?: string;
className?: string;
}
export function EmbeddedForm({
formSlug,
minHeight = '600px',
className = ''
}: EmbeddedFormProps) {
const [isLoaded, setIsLoaded] = useState(false);
const [iframeHeight, setIframeHeight] = useState(minHeight);
useEffect(() => {
// Listen for postMessage auto-resize events from the form
const handleMessage = (event: MessageEvent) => {
if (event.data?.type === 'INFIFORM_RESIZE' && event.data.height) {
setIframeHeight(`${event.data.height}px`);
}
};
window.addEventListener('message', handleMessage);
return () => window.removeEventListener('message', handleMessage);
}, []);
return (
<div
className={`w-full relative overflow-hidden transition-all duration-200 ${className}`}
style={{ minHeight: iframeHeight }}
>
{!isLoaded && (
<div className="absolute inset-0 flex items-center justify-center bg-muted/20 animate-pulse rounded-xl">
<span className="text-sm text-muted-foreground">Loading form...</span>
</div>
)}
<iframe
src={`https://forms.yourdomain.com/f/${formSlug}`}
title="Form Intake"
width="100%"
height="100%"
style={{ height: iframeHeight, minHeight: '100%', border: 'none' }}
onLoad={() => setIsLoaded(true)}
allow="camera; microphone; autoplay; encrypted-media;"
loading="lazy"
className="w-full rounded-xl"
/>
</div>
);
}
3 Engineering Highlights of This Component
- Hydration-Safe Client Boundary: Marked with
'use client'to prevent Next.js server-side rendering mismatch errors. - Dynamic Height Synchronization (
postMessage): Listens for resize events sent from the form, smoothly adjusting container height in real time without inner scrollbars. - Animated Loading Skeleton: Displays a smooth pulse skeleton until the iframe finishes loading, preventing Cumulative Layout Shift (CLS = 0).
Conclusion: Developer-Grade Integration
Integrating forms into modern React applications should be as clean as importing a native UI component.
Deploy this component, eliminate hydration glitches, and embed fast, responsive forms seamlessly across your Next.js application.
Related Articles
How to Build a Custom Webhook Listener in Node.js / Next.js for Form Payloads
Step-by-step developer guide: building a production-ready Next.js App Router route handler to receive form webhooks, verify HMAC signatures, and handle errors.
Creating Accessible Web Forms: WCAG 2.1 Guidelines, ARIA Labels, and Tab Navigation
Accessible forms aren't just a legal compliance requirement; they improve usability for everyone. Here is the developer guide to WCAG 2.1 AA accessible web forms.
How to Embed Forms on Framer Websites Without Breaking Responsive Breakpoints
Framer's dynamic layout engine can cause embedded iframes to overflow on mobile. Here is how to embed responsive web forms seamlessly into Framer components.