profound-logoProfound CMS
⌘K
Admin
Theme
DocsTutorialBlogPhilosophy
DocsTutorialBlogPhilosophy

Hybrid

Collection of Pages with ComponentsTypes of ComponentsSetup server sent events (SSE) content refetchInstall Profound CMS as a proxyCEL Scripting in Template BuilderProject ScaffoldingMedia Library

Headless

Quick startSplit Screen JSON Component Builder with LLMComponent Zod Pull

REST API

REST API OverviewgetConnect your websitegetGET /routesgetGET /routegetGET /blocksgetGET /blocks/with-cel-cachegetGET /blocks/generatedgetGET /componentsgetGET /components/{name}getGET /dataset/{schema_name}getGET /content-changes (SSE)patchPATCH /dataset/{schema_name}postPOST /translationpatchPATCH /translationsgetGET /usagepostPOST /csvpatchPATCH /csv
All Systems Operational
Powered Byprofound-logo
Theme

Install Profound CMS as a proxy

setup admin panel proxy

Attaching the admin panel on your website is an easy step


Why is this required

This ensures your editing experience is seamless. With the admin panel attached to your website via a proxy, you can edit your website on the same URL and have a visual preview of the changes in real time. It also enables overlay editing which is a better user experience in editing the webpage.


Required Steps

Proxy setup (there are some caveats)

The proxy is a proxy.ts file in your project (in Next.js 16; on older Next.js it's middleware.ts). It behaves like a URL rewrite, resolving the /admin, /api, and /auth endpoints of your website to the CMS.

  • For localhost: you must use a tunnel (since CMS cannot access localhost directly)
  • Works seamlessly on deployed websites

Proxy Setup

// proxy.ts  (Next.js 16 β€” use middleware.ts on older Next.js)
import { createCmsProxy, cmsProxyMatcher } from 'cms-renderer/lib/proxy';
import type { NextRequest } from 'next/server';

const cmsProxy = createCmsProxy({
  // The CMS admin origin to proxy to.
  upstream: process.env.ADMIN_UPSTREAM_ORIGIN ?? 'https://cms.dev.tryprofound.com',
});

export default async function proxy(request: NextRequest) {
  return cmsProxy(request);
}

export const config = {
  matcher: cmsProxyMatcher,
};

createCmsProxy returns a handler you call with the incoming request. cmsProxyMatcher is the ready-made matcher covering /admin, /api, /auth, and admin-originated /_next and static-asset requests β€” so you don't have to hand-write the matcher array.

On older Next.js versions, name the file middleware.ts and export the handler as middleware instead of the default export:

export async function middleware(request: NextRequest) { return cmsProxy(request); } export const config = { matcher: cmsProxyMatcher };

Need to proxy extra paths? Pass additionalPaths: ['/my-path'] to createCmsProxy.

Now you can go to /admin on your site to access the admin panel. This enables live preview.


Overlay Editing & the Preview Route

Overlays and edit-mode are rendered by your preview route, not the static production route. The admin loads your site in edit mode (?edit_mode=true) and that request is served by ParametricRoutePreviewPage on a force-dynamic route, which forwards searchParams for you:

// app/cms-preview_/[...slug]/page.tsx
import { ParametricRoutePreviewPage } from 'cms-renderer/lib/renderer';
import { registry } from '@/lib/registry';
import { cmsConfig } from '@/lib/cms-config';

// Dynamic rendering β€” allows searchParams for edit_mode
export const dynamic = 'force-dynamic';

interface PageProps {
  params: Promise<{ slug: string[] }>;
  searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
}

export default async function PreviewPage({ params, searchParams }: PageProps) {
  const { slug } = await params;
  
  return (
    <ParametricRoutePreviewPage
      registry={registry}
      apiKey={cmsConfig.apiKey}
      websiteId={cmsConfig.websiteId}
      cmsUrl={cmsConfig.cmsUrl}
      params={Promise.resolve({ slug })}
      searchParams={searchParams}
    />
  );
}

You don't wire overlays manually β€” passing searchParams into the preview renderer is all that's needed. Your production route (app/[...slug]/page.tsx) stays static with ParametricRoutePage and needs no searchParams. See Setup Hybrid CMS Project for the full two-route setup.


How to Verify

  1. Go to /admin on your website
  2. Should ask you to login and immediately open the CMS admin panel
  3. Open your site from the admin and confirm overlays/live preview work automatically

Overlays and live previews should work automatically.


Next Steps

Set up the full production + preview routes in Setup Hybrid CMS Project.

Continue Reading
Previousβ€ΉSetup server sent events (SSE) content refetchNextCEL Scripting in Template Builderβ€Ί