ReactifySDK · Next.js
ReactifySDK is client-only. Keep Script and reactify-thread inside a "use client" boundary; server components can import that boundary as a child.
Why WordPress pops up but a bare Next embed opens the hosted record page
The embed only opens the in-page recorder when window.reactifyWprtEmbed.apiKey (or reactifyShopifyEmbed.apiKey) is set—exactly what the WordPress plugin does. Without it, "React To This" / "Stitch this" are target="_blank" links to https://api.reactionsaas.com/reactify/record.
1. Publishable API key
# .env.local
NEXT_PUBLIC_REACTIFY_API_KEY=rsk_live_your_publishable_key2. App Router (recommended)
Bootstrap the embed config in useLayoutEffect (and again on script onLoad) so the key is present when CTAs paint. Use a real thread id for beat/stitch modals.
// app/reactify/ThreadEmbed.tsx
"use client";
import { useLayoutEffect } from "react";
import Script from "next/script";
const SRC = "https://reactify-cdn.s3.us-east-2.amazonaws.com/reactify.js?v=1.1.34";
const APP_BASE = "https://api.reactionsaas.com";
declare global {
interface Window {
reactifyWprtEmbed?: { base: string; apiKey: string };
reactifyShopifyEmbed?: { base: string; apiKey: string };
REACTIFY_EMBED_BASE?: string;
}
}
function bootstrapReactifyEmbed(apiKey: string) {
if (typeof window === "undefined") return;
const cfg = { base: APP_BASE.replace(/\/+$/, ""), apiKey: apiKey.trim() };
window.reactifyWprtEmbed = cfg;
window.reactifyShopifyEmbed = cfg;
window.REACTIFY_EMBED_BASE = cfg.base;
}
export function ThreadEmbed() {
const apiKey = process.env.NEXT_PUBLIC_REACTIFY_API_KEY ?? "";
// Set config before reactify.js upgrades <reactify-thread> (same as WordPress wp_localize_script).
useLayoutEffect(() => {
if (apiKey) bootstrapReactifyEmbed(apiKey);
}, [apiKey]);
return (
<>
<Script
src={SRC}
strategy="afterInteractive"
onLoad={() => {
if (apiKey) bootstrapReactifyEmbed(apiKey);
}}
/>
{/* @ts-expect-error custom element */}
<reactify-thread
thread="YOUR_THREAD_ID"
data-base={APP_BASE}
/>
</>
);
}// app/page.tsx (Server Component)
import { ThreadEmbed } from "./reactify/ThreadEmbed";
export default function Page() {
return (
<main>
<h1>Drop</h1>
<ThreadEmbed />
</main>
);
}Pages Router
Set window.reactifyWprtEmbed in pages/_app.tsx (client) before next/script with strategy="afterInteractive", or dynamically import a client-only section that bootstraps then loads the custom element.
Images & video domains
If you wrap media with next/image, keep thread source playback on plain URLs inside the embed—the custom element handles its own media. Add your storage host to images.remotePatterns only if you mirror assets through Next.