Next.js on Faustine
Faustine supports Next.js for Web Agents, with the App Router and with the Pages Router. A Next.js agent is installed as a React component, signs the user's identity on your server, and with the App Router can call Server Actions through an adapter in your repository.
Get started
What each router supports
| Feature | App Router | Pages Router |
|---|---|---|
<FaustineAgent> component |
Yes, from the root layout | Yes, from pages/_app.tsx |
Identity signed on the server with faustineIdentityToken |
Yes, in the root layout | Yes, in an API route |
| Routes read from the filesystem | Yes | Yes |
| Navigation through the Next.js router | Yes | Yes |
| Page re-rendered after the agent writes | Yes | No |
| Adapter for Server Actions and server-only functions | Yes | No |
Analysis
The analysis finds the Next.js app in your repository by its package.json: the root of the repository, or a directory up to two levels below it, such as web/ or apps/site/. It reads which router the app uses from the app/ or pages/ directory, also under src/.
The list of routes comes from the files. The analysis writes a description for each one.
| File | Route |
|---|---|
app/(marketing)/pricing/page.tsx |
/pricing |
app/deals/[id]/page.tsx |
/deals/:id |
app/docs/[...slug]/page.tsx |
/docs/:slug* |
pages/users/[id]/settings.tsx |
/users/:id/settings |
Route groups add no segment. Parallel routes (@slot), intercepting routes, folders that start with _ and everything under api are not listed as pages.
Route handlers (route.ts files under app/) are read as the app's own API, so the agent gets actions for them even when no client component calls them. See The analysis.
Sessions
When the app authenticates with a cookie session, the agent's requests are sent with the user's cookies. The agent acts as the signed-in user and sees what that user sees.
If the session has expired and a request ends on your sign-in page, the action fails with an error that says the user is not signed in.
Data surface
A Next.js app can keep its data where the browser has no URL to call. The analysis summary has a Data surface card that sorts the app's data access into Reachable now (route handlers and client-side fetches), Reachable with the adapter (Server Actions and server-only data functions) and Not reachable (reads written inline in a Server Component).
For a read in the last group, the card suggests the data function to extract. After you extract it and push, it moves to the second group.
Server Actions and the adapter
The Faustine adapter gives Server Actions and server-only data functions a URL inside your own app. npx faustine-next init writes a registry of the functions you expose and a route handler at app/api/faustine/[...op]/route.ts. The agent calls the handler from the browser with the user's cookies, and the handler runs only the operations that are in the registry and enabled in the portal.
The adapter needs the App Router. See The Faustine adapter for Next.js.
Navigation and refresh
The agent moves between pages with the Next.js router, so the destination renders without a full page load. If the router is not on the page, the agent loads the destination with a full page load.
After every action that writes, the agent refreshes the current route. In the App Router this re-renders the Server Components of the current route, so the page shows what the agent changed. Several writes in one step refresh the page once. Every call through the adapter counts as a write. See Navigation.
Identity
faustineIdentityToken from @faustine-ai/next signs the user's identity token on your server with FAUSTINE_IDENTITY_SECRET, and <FaustineAgent identityJwt={…}> passes it to the widget. The secret never reaches the browser.
import { faustineIdentityToken } from '@faustine-ai/next';
const identityJwt = user
? faustineIdentityToken({ id: user.id, name: user.name, email: user.email })
: null;Build SHA
withFaustine wraps your Next.js config and records the commit of the build, so the portal can show which commit the running app was built from. It is optional and only has an effect with the adapter.
import type { NextConfig } from 'next';
import { withFaustine } from '@faustine-ai/next';
const nextConfig: NextConfig = {};
export default withFaustine(nextConfig);The commit is read at build time from the first of these variables that is set: FAUSTINE_BUILD_SHA, VERCEL_GIT_COMMIT_SHA, GITHUB_SHA, CF_PAGES_COMMIT_SHA, COMMIT_REF, SOURCE_VERSION. The adapter's handler includes it in GET /api/faustine/manifest and in the x-faustine-build response header. In the portal, the Deployed cell under Settings > Faustine adapter shows its first 7 characters.
Environments
<FaustineAgent> loads the Production environment unless you pass env. The adapter's handler reads the enabled operations of Production unless FAUSTINE_ENV is set on the server. When a deployment serves another environment, set both to the same name.
More resources
Next steps
- Install in Next.js: the install card, the component and the identity secret.
- Let your agent call Server Actions: the adapter from start to finish on the Next.js version of Nimbus CRM.
Last updated November 13, 2026