# Page Zero Next.js Installation and Migration Guide

Updated: 2026-10-07. Next.js 16 App Router, React 19, Node.js runtime; target: @soloworks/smking-next 0.23.1.
Next.js 15 must remain on SDK 0.22.2/API v1; do not upgrade the framework automatically. Pages Router is outside this guide's scope.
This is the shared installation guide used by the Dashboard and CLI. The CLI connects a site; your coding assistant integrates and verifies the SDK.

## 1. Inspect the project and connect

On a development branch, read package.json, the lockfile, App Router routes, next.config.*, metadata, proxy/middleware and existing CMS/SEO integration.
Preserve authentication, cookies, redirects, rewrites, locales, metadata, sitemap and robots behavior. Do not deploy or modify production configuration automatically.

```bash
pnpm dlx @soloworks/smking-wizard@latest connect
```

Use CLI 0.10.0 or later. It asks for your website's HTTPS origin; enter the actual website you want to connect, not a Git repository URL or an example domain.
It then opens browser OAuth: sign in, select the matching workspace and site, and authorize the connection.
The CLI checks that the selected site's domain matches your input and asks for confirmation before writing local settings.
The optional --site-url argument supplies a known origin instead of the prompt; it does not skip OAuth or confirmation.
SMKING_SAAS_URL selects the Page Zero backend; the default is https://getpagezero.com. Set it explicitly only for a different authorized backend.
The CLI does not install the SDK or activate delivery. Keep SMKING_API_KEY, SMKING_BASE_URL and SMKING_WEBHOOK_SECRET from the same site/environment on the server, not in NEXT_PUBLIC_*.
Never put secrets in logs, Markdown or chat.

For Next.js 16, pin and review the package and lockfile:

```bash
pnpm add --save-exact @soloworks/smking-next@0.23.1
```

Use the project's existing package manager and build scripts. For Next.js 15, pin 0.22.2 and retain API v1.
The SDK ships TypeScript: add "@soloworks/smking-next" to the existing transpilePackages array in next.config.* without replacing other settings.

## 2. Prepare API v2 and site settings

Installing the SDK does not activate v2. Preserve existing settings until Page Zero confirms source reads, published snapshots, delivery infrastructure, notification resources and the webhook destination are ready.
Replace all bracketed values with settings for the selected site; use its actual CMS mount only if CMS is enabled:

```dotenv
SMKING_API_KEY=<site publishable key>
SMKING_BASE_URL=<Page Zero origin for the selected environment>
SMKING_CONTENT_API_VERSION=2
SMKING_WEBHOOK_SECRET=<webhook secret for the same site>
SMKING_DELIVERY_NOTIFICATIONS_SCOPE=<64-character lowercase hexadecimal scope supplied by the same Page Zero source>
SMKING_DELIVERY_NOTIFICATION_RESOURCES=<comma-separated enabled notification resources>
SMKING_CMS_PATH=<chosen CMS mount path, if used>
```

Supported notification resources are aeo,cms-page,site-file. Include only resources the project uses, without spaces or duplicates.
Do not copy Laravel's markdown resource, DELIVERY_MODE, LOCAL_STORE_PATH or NOTIFICATIONS_ENABLED settings.
Do not add a customer database, durable content store, SDK-private cache or Laravel background commands.

## 3. Add AEO without changing rendering policy

AEO belongs in server-rendered HTML. Pass the same known route path to content and metadata reads; the application chooses SSR, SSG or ISR.
Do not force dynamic rendering for visitor reporting. Obtain the canonical path from the project's existing route logic; no particular page or URL is required.
These helpers illustrate integration into existing page and generateMetadata code, not a required route structure:

```tsx
import type { Metadata } from "next";
import { SmkingAEO, withSmkingMetadata } from "@soloworks/smking-next";

export async function pageMetadata(hostMetadata: Metadata, pagePath: string) {
  return withSmkingMetadata(hostMetadata, {
    apiKey: process.env.SMKING_API_KEY!,
    path: pagePath,
  });
}

export function PageAeo({ pagePath }: { pagePath: string }) {
  return <SmkingAEO apiKey={process.env.SMKING_API_KEY!} path={pagePath} includeSeo={false} />;
}
```

Preserve the original page content and metadata. Use includeSeo={false} when metadata is handled by withSmkingMetadata; canonical merges through Next.js alternates rather than a second set of SEO tags.
Do not also add pathless automatic AEO to the root layout. Automatic mode needs the current request path and is a separate request-aware integration.
Optional visitor reporting uses smkingProxy from "@soloworks/smking-next/proxy" independently of content rendering. Next.js 16 uses proxy.ts; Next.js 15 uses middleware.ts.
Preserve existing proxy responses, cookies, redirects and rewrites. Content still works without reporting integration; it does not require reading visitor requests during content rendering.

## 4. Integrate CMS, preview and webhook where used

For CMS, place SmkingRuntime once in the layout for the chosen CMS mount, not in each article:

```tsx
import { SmkingRuntime } from "@soloworks/smking-next";
export default function Layout({ children }: { children: React.ReactNode }) {
  return <><SmkingRuntime apiKey={process.env.SMKING_API_KEY!} />{children}</>;
}
```

Use an optional catch-all page under that mount to cover the root, articles and nested slugs. Resolve conflicts with existing routes rather than overwriting them:

```tsx
import { SmkingCms, withSmkingCmsMetadata } from "@soloworks/smking-next/cms";
import type { ResolvingMetadata } from "next";

type Props = {
  params: Promise<{ slug?: string[] }>;
};

async function cmsParams({ params }: Props) {
  const { slug } = await params;
  return { apiKey: process.env.SMKING_API_KEY!, slug: slug?.join("/") ?? "" };
}

export async function generateMetadata(props: Props, parent: ResolvingMetadata) {
  return withSmkingCmsMetadata({}, await cmsParams(props), parent);
}

export default async function Page(props: Props) {
  return <SmkingCms {...(await cmsParams(props))} includeSeo={false} />;
}
```

This native CMS metadata integration requires an SDK version exporting
withSmkingCmsMetadata; it is not included in 0.23.1 or earlier.
It is currently available in the opt-in prerelease 0.23.2-beta.1; install that
exact version only when prerelease testing is approved. The stable installation
command above remains on 0.23.1 until a stable release includes the helper.
Keep the host layout's default metadata. The page's generateMetadata supplies
the CMS title, search description, canonical and Open Graph fields through
Next.js, while includeSeo={false} prevents duplicate inline tags. Empty CMS
fields preserve host defaults; pass parent to preserve the layout's nested
Open Graph fields and language alternates. Metadata and body share the request's published
or private Draft Mode result; JSON-LD remains in SmkingCms.

Expose the SDK's preview and webhook handlers at their integration endpoints:

```ts
// app/smking-preview/route.ts
export { GET } from "@soloworks/smking-next/preview";
```

```ts
// app/api/smking/webhook/route.ts
export { POST } from "@soloworks/smking-next/webhook";
```

AEO-only v2 updates and withdrawals also need the webhook; it is not only for CMS.
Keep Draft Mode requests separate from public caching. Compose existing sitemap, robots and llms.txt behavior rather than replacing it.
Use smking-next install only for missing integration files after reviewing --help.

## 5. Use Next.js native caching

The standard App Router integration uses native caching. Default revalidation is 300 seconds for CMS and 3600 seconds for AEO; the host can configure revalidate.
Normal webhook updates use revalidateTag(tag, "max"); explicit withdrawals invalidate immediately. HTTP 200 means accepted, not that every cached page has already rendered the revision.
Subsequent requests perform revalidation/rendering. TTL plus subsequent requests recover missed notifications; this is not scheduled downloading.

Cache Components is an application choice, not an SDK requirement. If enabled, use the public read-only entry points:

```ts
import { cacheLife, cacheTag } from "next/cache";
import { fetchPublishedAeo, aeoCacheTags } from "@soloworks/smking-next/delivery";
export async function publishedAeo(source: string, key: string, path: string) {
  "use cache";
  cacheLife({ stale: 0, revalidate: 3600, expire: 86400 });
  cacheTag(...aeoCacheTags(source, key, path));
  return fetchPublishedAeo(source, key, path);
}
```

Use fetchPublishedCms/cmsCacheTags for CMS and fetchPublishedSiteFile/siteFileCacheTags for site files.
Read request context outside cached functions and pass explicit identity. Do not report visitors or convert temporary failures into cached empty values inside them.
Handle temporary failures outside the cache: omit unavailable AEO; let CMS use the application's error boundary or an explicit 503.
Native caches can be evicted. If the cache has no content and Page Zero delivery is unavailable, permanent content availability is not guaranteed. After recovery, the next read can restore content without editing it again.
Distinguish absence/withdrawal from temporary failure. Do not turn source failures into an empty CMS 200 or a false 404, and do not render explicitly revoked content.

## 6. Verify, deploy and monitor

```bash
pnpm exec smking-next doctor --json --surfaces=aeo,cms
pnpm build
```

Choose only the surfaces actually enabled. Passing doctor does not prove source activation or deployment.
Use representative project routes: inspect production-build static/dynamic behavior and complete HTML for non-CMS SEO/AEO and, when enabled, CMS root/articles/nested paths.
Test public content before/after Draft Mode, updates, withdrawals, missed-notification TTL, cold/warm caches, source outages and recovery.
Keep test content and evidence available for inspection. Development-server behavior does not prove production cache behavior.

Apply environment changes through the host's normal redeployment workflow. Keep each deployment paired with settings for the same Page Zero environment; do not copy test keys/scopes to production.
Verify the actual deployment revision, SDK version, source identity and content rather than assuming a hosting provider or a fixed domain.
Observe source reads, actual CDN results, application latency/error rates, webhook acceptance and visible revision timing.
Do not apply Laravel's zero visitor-content-read expectation to Next.js. Optional low-volume health reporting does not update content or prewarm caches and is not a required installation schedule.
Roll back with a reviewed lockfile and deployment, preserving withdrawal safety. Do not blindly switch to v1 or downgrade the framework.

## Native platform references

- [Next.js revalidateTag](https://nextjs.org/docs/app/api-reference/functions/revalidateTag)
- [Next.js use cache](https://nextjs.org/docs/app/api-reference/directives/use-cache)
- [Contentful and Cache Components](https://www.contentful.com/blog/nextjs-cache-components/)
