Next.js
Editpix works with the App Router (Next 13, 14, 15, 16). The canvas engine runs in the browser, so you want ssr: false.
Install
Terminal
npm install @editpix/react
Dynamic import
Keep Editpix out of your server bundle to shave ~45KB gzipped off your initial response.
app/edit/page.tsx
"use client";
import dynamic from "next/dynamic";
const EditpixEditor = dynamic(
() => import("@editpix/react").then((m) => m.EditpixEditor),
{ ssr: false, loading: () => <EditorSkeleton /> },
);
export default function EditPage({
searchParams,
}: {
searchParams: { url: string };
}) {
return (
<main className="h-[calc(100vh-64px)] p-6">
<EditpixEditor
apiKey={process.env.NEXT_PUBLIC_EDITPIX_KEY!}
imageUrl={searchParams.url}
onSave={async (blob) => {
const form = new FormData();
form.append("file", blob);
const res = await fetch("/api/upload", { method: "POST", body: form });
const { url } = await res.json();
window.location.href = `/preview?url=${encodeURIComponent(url)}`;
}}
/>
</main>
);
}Route handler for uploads
app/api/upload/route.ts
import { NextResponse } from "next/server";
import { put } from "@vercel/blob";
export async function POST(req: Request) {
const form = await req.formData();
const file = form.get("file") as File;
const { url } = await put(`edited/${crypto.randomUUID()}.png`, file, {
access: "public",
});
return NextResponse.json({ url });
}CSP tip. If you ship a strict Content Security Policy, add
'wasm-unsafe-eval' to script-src. Editpix uses a small WebAssembly decoder for JPEG progressive scans.