SKILL.md
Full skill instructions
Next.js + Enonic XP Headless Integration (Next.XP)
Procedures
Step 1: Identify the workspace integration surface
- Inspect the workspace for Next.js entry points (
next.config.*,package.jsonwithnextdependency), Enonic XP app markers (build.gradlewithcom.enonic.xp), or existing Next.XP adapter references (@enonic/nextjs-adapter). - Execute
node scripts/find-nextxp-targets.mjs .to inventory Next.js projects,.envfiles withENONIC_*variables, component mapping files (_mappings.ts), and Guillotine query files when a Node runtime is available. - If a Node runtime is unavailable, inspect
package.json,.env, andsrc/components/_mappings.tsmanually to identify the integration surface. - If the workspace contains both an Enonic XP app and a Next.js frontend, confirm which side the task targets before proceeding.
- If the workspace is not a Next.js + Enonic XP project, stop and explain that this skill does not apply.
Step 2: Configure the Enonic adapter
- Read
references/nextxp-reference.mdbefore writing or modifying configuration. - Verify or create the
.env(or.env.localfor local development) file in the Next.js project root with the required variables:ENONIC_API_TOKEN— shared secret for preview mode authentication.ENONIC_APP_NAME— fully qualified Enonic application name (e.g.,com.example.myproject).ENONIC_MAPPINGS— locale-to-project/site mapping (e.g.,en:intro/hmdb).ENONIC_API— base URL for the Guillotine API endpoint (e.g.,http://127.0.0.1:8080/site/).
- Install the
@enonic/nextjs-adapterpackage if not already present:npm install @enonic/nextjs-adapter. - Import
@enonic/nextjs-adapter/baseMappingsat the top ofsrc/components/_mappings.tsto register built-in component renderers. - Verify the Next.js project was scaffolded from the
nextxp-templateor contains the expected file structure:src/components/_mappings.ts,src/app/[locale]/[[...contentPath]]/page.tsx, and API routes undersrc/app/api/. - Read
references/compatibility.mdto confirm version requirements between@enonic/nextjs-adapter(v4.x), Next.js (16+), React (19), and Enonic XP.
Step 3: Map content types to React components
- Read
references/nextxp-reference.mdfor the component registry API and mapping patterns. - Read
references/examples.mdfor complete content type mapping examples including queries, views, and processors. - For each Enonic content type that needs a custom rendering:
a. Create a Guillotine GraphQL query function in
src/components/queries/that fetches the fields specific to that content type using type introspection (... on AppName_ContentTypeName). b. For content types with HTML area (rich text) fields, userichTextQuery(fieldName)from@enonic/nextjs-adapterto generate the query fragment. Seereferences/nextxp-reference.mdfor the rich text rendering section. c. Create a React view component insrc/components/views/that acceptsFetchContentResultprops and renders the fetched data. UseRichTextViewfrom@enonic/nextjs-adapter/views/RichTextViewfor HTML area fields. d. Register both insrc/components/_mappings.tsusingComponentRegistry.addContentType(). - For page components (pages, parts, layouts):
a. Define the component XML in the Enonic app under
src/main/resources/site/pages/,parts/, orlayouts/. b. Create a corresponding React component insrc/components/pages/,parts/, orlayouts/. UseLayoutPropsfor layouts and the namedRegionViewexport for individual region rendering. c. Register usingComponentRegistry.addPage(),ComponentRegistry.addPart(), orComponentRegistry.addLayout(). - For layouts, use
LayoutPropstype andRegionView(singular, named export) for individual regions instead ofRegionsView. - Use
APP_NAMEandAPP_NAME_UNDERSCOREDimports from@enonic/nextjs-adapterto keep content type references dynamic.
Step 4: Configure Guillotine data fetching
- Read
references/nextxp-reference.mdfor the Guillotine query structure and variable passing. - Write GraphQL queries that use
$path:ID!as the primary variable for content retrieval viaguillotine { get(key:$path) { ... } }. - Use type introspection to access content-type-specific fields:
... on AppName_ContentTypeName { data { ... } }. - For rich text fields (HtmlArea), use
richTextQuery(fieldName)from the adapter instead of querying the field directly. Render withRichTextViewfrom@enonic/nextjs-adapter/views/RichTextView. - For parts and configurable components, export a query object with
query(path, context, config)andvariables(path, context, config)functions. - Use processors (optional async functions) to post-process query results before passing to the view.
- Use
ComponentRegistry.setCommonQuery()for data shared across all page components. Remove the common query if not needed to optimize performance. - Use
getUrl()andgetAsset()helper functions from the adapter for URL handling that works in both standalone and Content Studio preview modes. - For macros in rich text, register them with
ComponentRegistry.addMacro()before other components that useRichTextView. Seereferences/nextxp-reference.mdfor the macro registration API.
Step 5: Enable Content Studio preview mode
- Read
references/nextxp-reference.mdfor full preview architecture details. - Install the
Next.XPapp in Enonic XP:XP Menu → Applications → Install → search "Next.XP". - Add the Next.XP app to the target site in Content Studio via the "Applications" combobox on the site edit view.
- Verify default preview configuration: URL
http://127.0.0.1:3000and secret matchingENONIC_API_TOKEN. - For production, configure the Next.XP app with the deployed Next.js URL and shared secret via app config:
nextjs.default.url = <Next.js app URL> nextjs.default.secret = <shared secret> - Preview mode automatically switches the Guillotine API to the
draftbranch, while the public Next.js frontend uses themaster(published) branch. - Use
getUrl()in all component links to ensure URLs resolve correctly across preview, inline, and edit modes in Content Studio. - If preview shows a blank page, read
references/troubleshooting.mdfor diagnostic steps.
Step 6: Deploy to production
- Read
references/nextxp-reference.mdfor the deployment checklist. - Deploy the Enonic app to Enonic Cloud using
enonic cloud app install. - Create an ingress in Enonic Cloud to expose the Guillotine API (target path
/site, public path/api). - Deploy the Next.js app to Vercel or another hosting platform.
- Set production environment variables:
ENONIC_API,ENONIC_APP_NAME,ENONIC_API_TOKEN,ENONIC_MAPPINGS. - Configure the Next.XP app in Enonic Cloud to point to the production Next.js URL.
- Publish content in Content Studio to make it visible on the live frontend.
Step 7: Validate the integration
- Execute
node scripts/find-nextxp-targets.mjs .to confirm the adapter, mappings, and env configuration still resolve correctly. - Verify that standalone Next.js rendering works at
http://localhost:3000with published content. - Verify Content Studio preview renders correctly for both draft and published content.
- Test content type mappings by visiting content URLs and confirming custom views render.
- Use
validateData()from@enonic/nextjs-adapterin the page handler to catch invalid content responses. Seereferences/nextxp-reference.mdfor the SSG page handler pattern. - Run the workspace build (
npm run build) to catch TypeScript or build errors.
Error Handling
- If Content Studio preview shows a blank page, read
references/troubleshooting.mdfor preview proxy diagnostics, token mismatch detection, and CORS issues. - If Guillotine queries return empty or unexpected data, verify the content type name matches the introspection pattern and test the query in GraphQL Playground at
http://localhost:8080/site/<project>. - If
@enonic/nextjs-adapterimports fail, checkreferences/compatibility.mdfor version requirements and confirm the package is installed. - If content renders in preview but not on the public site, verify the content is published (moved from
drafttomasterbranch). - If component mappings are not applied, verify registrations in
_mappings.tsuse the correct fully-qualified content type or component name withAPP_NAME.
