← Back to blog

Adding an Interactive Demo to a React or Next.js Site

August 18, 2026

Dropping an iframe into a React component takes one line. Doing it without damaging your Largest Contentful Paint and Cumulative Layout Shift takes slightly more thought, and this is the part most guides skip.

Everything here applies to Next.js App Router, Pages Router and plain React alike.

A component worth copying

Wrap the iframe in a container with a fixed aspect ratio so the browser reserves the space before the frame loads. Without that you get a layout shift when it arrives, and CLS is the metric most easily damaged by an embed.

Give the iframe `loading="lazy"` when it sits below the fold, a `title` for accessibility, and `border: 0`. Set width and height to 100% of the ratio container rather than fixed pixels.

Do not let it block the hero

  • Below the fold: `loading="lazy"` is enough, and it is the default sensible choice.
  • Above the fold: load it eagerly, but make sure nothing else large competes -- an embed and a hero video together will lose.
  • Behind a click: render a static poster image with a play affordance and swap in the iframe on click. Best Core Web Vitals, at the cost of one extra interaction.
  • Never `next/dynamic` an iframe with `ssr: false` for performance. An iframe is not JavaScript; it costs nothing at build and the dynamic import adds a client round trip.

Content-Security-Policy

If your site sends a CSP header -- and a Next.js site with a security middleware often does -- the demo host must be allowed in `frame-src`. Miss it and the frame is blocked silently in production while working perfectly in local development, which is a genuinely miserable hour to debug.

Add the demo domain to `frame-src` explicitly rather than relaxing the policy, and check the browser console on the deployed site rather than trusting a local run.

Server components and hydration

An iframe embed needs no client-side JavaScript at all, so keep the wrapper a server component in the App Router. Marking it `use client` for no reason ships JavaScript you do not need.

The only case for a client component is the click-to-load pattern above, where you genuinely need state to swap the poster for the frame.

Frequently asked questions

How do I embed an interactive demo in a Next.js site?
Render an iframe inside a fixed-aspect-ratio container so the browser reserves space before it loads, with loading="lazy" when it sits below the fold. It needs no client JavaScript, so keep the wrapper a server component in the App Router.
Why is my embedded demo blocked in production but fine locally?
Almost always Content-Security-Policy. If your site sends a CSP header, the demo host must appear in frame-src, and local development often runs without the header. Add the domain explicitly and check the console on the deployed site.
How do I stop an embedded demo from hurting Core Web Vitals?
Reserve the space with an aspect-ratio container to avoid layout shift, lazy-load anything below the fold, and for the strictest budgets render a static poster image and swap in the iframe on click -- which costs one interaction and almost nothing in load time.

Keep reading

This is what Demorta does

Click through it — the same kind of demo you can record of your own product.

Try it on your own product

Record your first interactive demo free.

Five demos on the free plan, forever. No credit card, no trial countdown, no sales call. Install the Chrome extension, click through your product once, and you have a shareable link in about ten minutes.

Start free →