docs
    site-kit: Managed landing pages
    v8.12.0.md

    Managed landing pages

    Use the server entry for an opt-in managed landing route. The same bounded layout supports a newsletter signup, a requested guide or an inquiry. Page text renders on the server and follows the site's existing layout. Managed forms handle browser submission.

    First check your site's route inventory for /f collisions. Install this adapter only when the prefix is available, then verify the deployed route before enabling managed publication in Sonor. Existing-page funnels work independently of this adapter.

    // app/f/[slug]/page.tsx
    import { notFound } from 'next/navigation'
    import {
      getPublishedFunnelPage,
      managedFunnelMetadata,
      ManagedFunnelPage,
    } from '@sonordev/site-kit/website/landing/server'
    
    const options = { site: 'example.com' } // Your registered site host.
    type PageProps = { params: Promise<{ slug: string }> }
    
    export async function generateMetadata({ params }: PageProps) {
      const { slug } = await params
      const page = await getPublishedFunnelPage(slug, options)
      return page ? managedFunnelMetadata(page) : { robots: { index: false } }
    }
    
    export default async function Page({ params }: PageProps) {
      const { slug } = await params
      const page = await getPublishedFunnelPage(slug, options)
      if (!page) notFound()
      return <ManagedFunnelPage page={page} />
    }

    Keep SiteKitLayout in your root layout and use its deferred analytics sibling. The adapter doesn't require analytics to submit a form. It reads the server credential through the existing server transport and requires an explicit registered site. Responses from another host or path are refused.

    Published-page reads use no-store in this version so an outdated or removed publication isn't served from the fetch cache. Keep the route dynamic and avoid wrapping this reader in a persistent cache. managedFunnelMetadata defaults to noindex, nofollow. Keep these campaign routes out of your sitemap.

    On Next.js 16.3 and later with Cache Components, instant = false applies only to this per-request route. There isn't a useful static publication shell: the content and its availability both come from the fresh read. Navigation waits for that read, so the complete content and managed form arrive as readable server HTML, including without JavaScript. Keep the reader uncached and verify visible content with JavaScript disabled.

    Add this export to the page only when cacheComponents: true is enabled in your Next config; Next rejects it when Cache Components is off:

    export const instant = false

    Use the normal revalidation route:

    // app/api/seo-revalidate/route.ts
    export { POST } from '@sonordev/site-kit/revalidate'

    Sonor can invalidate the exact published path and SITE_CACHE_TAGS.funnels. That refresh is distinct from installing and verifying the route.

    Private previews use the exact owner-authorized dashboard DTO. Pausing follow-ups retains the published landing page and independent form confirmations. FunnelPageContent from the server entry accepts preview and displays an inert form placeholder with a noindex and reporting-suppression marker. ManagedFunnelPage preview also skips form fetching. Serve private preview responses with Cache-Control: no-store; these components don't authorize requests or set HTTP headers. No public draft-token route is included.

    Content is limited to text paragraphs and bullet lists. Logos use resolved, validated asset URLs, colors and fonts use the shared brand contract, and the renderer accepts no stored HTML, scripts or CSS. If a full logo is missing, the verified display name appears. Theme variants, square marks and publisher attribution retain their separate roles.

    For developer-authored paid pages, the existing LandingPage component remains available from @sonordev/site-kit/website/landing. Import landingPageMetadata from the server entry. Campaign normalization now comes from the shared contracts package.

    Record the installation

    An authorized repository owner completes this checklist once per site:

    1. Inventory the whole /f prefix, including routes, rewrites and dynamic route collisions.
    2. Install the adapter above and verify server-rendered content, form behavior, exact host binding, private preview isolation and mobile/desktop layouts for that source revision.
    3. Record the inventory digest, source revision, supported adapter version and named verification through the existing owner-authorized project settings path.

    The installation record lives at projects.settings.managed_funnel_pages[normalizedOwnedHost]. It contains schemaVersion: 1, enabled, prefix: '/f', adapterVersion, routeInventoryDigest, sourceRevision, verifiedAt, verifiedBy and provenance: 'owner_installation_attestation'. The server attributes the actor and provenance. Use the adapter version supported by your Sonor installation. Each record belongs to one registered host.

    A draft or a browser report can't assert that the route is installed. This record describes an operator's installation check. Report a verified deployment and current live reachability separately when you've observed them. Publishing a funnel doesn't install the adapter.

    Disable the record before removing the adapter. For route, host or adapter changes, invalidate the old record, repeat the checks and replace its revision and digest. Sonor snapshots this installation evidence during preview and rechecks it at launch and public resolution. Existing-page funnels remain available when managed-page installation is missing.