# For CMS + Next.js developers

Integrate the erxes CMS with Next.js: setup, data queries, rendering, and migration.


Integrate the erxes CMS with a Next.js application: environment setup, querying CMS content over GraphQL, server- and client-side rendering, and migrating an existing integration. This track is for developers running (or building) a Next.js website that displays posts, pages, menus, categories, and tags managed in erxes. The guides assume the App Router and native `fetch`; the same GraphQL documents work with Apollo Client or another GraphQL client.

## Prerequisites

- An erxes instance with the **Content** plugin enabled (see [Local setup](https://erxes.io/docs/local-setup) or [Self-hosting](https://erxes.io/docs/self-hosting)).
- A **Client Portal** created for your website, with its CMS records (posts, pages, menus) associated to that portal.
- The portal's token and your deployment's gateway URL (for example `https://YOUR_TENANT.app.erxes.io/gateway/graphql`, or `http://localhost:4000/graphql` in a local setup).

## How authentication works

The website's server sends the Client Portal token as the `x-app-token` header on every GraphQL request. The gateway verifies the JWT and identifies the portal named by its `clientPortalId` claim; the token identifies **which website** is asking, and every `cp*` operation is scoped to that portal automatically. A separate `client-auth-token` identifies a signed-in portal user, and an `erxes-app-token` authenticates an application principal for administrative work. Keep all of these on the server; none belongs in browser code or `NEXT_PUBLIC_*` variables.

## Two operation families

- `cp*` operations serve client-portal integrations. They derive the portal from `x-app-token`, so a public website only ever sees its own content.
- `cms*` operations serve the admin UI and authenticated tooling. They need a team-member session or an Apps token, and most require an explicit `clientPortalId` argument.

The `cp*` prefix is not a read-only or published-only guarantee: `cpPost` returns a record regardless of status and there are `cp*` mutations. The guides show where to enforce `status: published` and how to limit the browser to a fixed endpoint.

## Guides

- [Introduction](https://erxes.io/docs/content-plug-cms-next-developers-introduction): How the CMS + Next.js track is organized and what you need before you start
- [Setup](https://erxes.io/docs/content-plug-cms-next-developers-setup): Set up your development environment for CMS integration with Next.js
- [Queries](https://erxes.io/docs/content-plug-cms-next-developers-queries): Every CMS GraphQL query and mutation, with arguments and examples
- [SSR Fetching](https://erxes.io/docs/content-plug-cms-next-developers-ssr): Fetch CMS data on the server in Next.js App Router pages and handle caching safely
- [CSR Fetching](https://erxes.io/docs/content-plug-cms-next-developers-csr): Fetch CMS data from the browser without exposing administrative credentials
- [CMS Migration](https://erxes.io/docs/content-plug-cms-next-developers-cms-migration): Move posts, categories, and pages from another CMS into the erxes CMS

