@webmaxru/enonic-controller-generator
Generates Enonic XP controller files (TypeScript/JavaScript) and paired XML descriptors for pages, parts, and layouts. Covers lib-portal imports, HTTP handler exports, region definitions, Thymeleaf/Mustache rendering, and response processors. Use when scaffolding page controllers with regions, part controllers with config access, layout controllers with multi-region support, or response processors for Enonic XP sites. Do not use for content type schemas, headless Next.js/React frontends, GraphQL Guillotine queries, or non-Enonic web frameworks.
| name | enonic-controller-generator |
| description | Generates Enonic XP controller files (TypeScript/JavaScript) and paired XML descriptors for pages, parts, and layouts. Covers lib-portal imports, HTTP handler exports, region definitions, Thymeleaf/Mustache rendering, and response processors. Use when scaffolding page controllers with regions, part controllers with config access, layout controllers with multi-region support, or response processors for Enonic XP sites. Do not use for content type schemas, headless Next.js/React frontends, GraphQL Guillotine queries, or non-Enonic web frameworks. |
| license | MIT |
Enonic XP Controller Generator
Procedures
Step 1: Detect Enonic XP Project
- Execute
node scripts/find-enonic-targets.mjs <workspace-root>to locate the project root and existing components. - If the script exits with code 1 (no markers found), inform the user that no Enonic XP project was detected and stop.
- Record the
sitePathfrom stdout — all generated files target directories relative to this path.
Step 2: Determine Component Type
- Identify which component type the user requires:
- Page — renders a full page, may declare one or more regions.
- Part — a leaf component with a config form, no regions.
- Layout — organizes other components via named regions.
- Response processor — a site-level filter that modifies the HTTP response (e.g., inject scripts).
- If the request is ambiguous, ask the user to clarify the component type before proceeding.
Step 3: Gather Component Details
- Ask for or infer the following:
- Component name (kebab-case, e.g.,
hero-banner). - Display name (human-readable, e.g.,
Hero Banner). - Language — TypeScript (
.ts, default) or JavaScript (.js). Readreferences/compatibility.mdfor guidance on TS vs JS differences. - Template engine — Thymeleaf (default) or Mustache.
- For pages/layouts: region names (default:
mainfor pages). - For parts: form fields (name, type, occurrences).
- For response processors: page contribution target (
bodyEnd,headEnd, etc.) and the content to inject.
- Component name (kebab-case, e.g.,
Step 4: Generate the XML Descriptor
- Read
references/controller-reference.mdfor the XML descriptor schema. - Create the descriptor file:
- Page:
<sitePath>/pages/<name>/<name>.xml - Part:
<sitePath>/parts/<name>/<name>.xml - Layout:
<sitePath>/layouts/<name>/<name>.xml
- Page:
- Include
<display-name>,<description>,<form>(with inputs for parts), and<regions>(for pages and layouts).
Step 5: Generate the Controller
- Read the appropriate template from
assets/:assets/page-controller.template.tsfor pages.assets/part-controller.template.tsfor parts.assets/layout-controller.template.tsfor layouts.
- Replace placeholders with the actual component name, config field mappings, region names, and library imports.
- If JavaScript was requested, convert the ES module syntax to CommonJS (
require/exports). - Read
references/controller-reference.mdfor the Portal API surface (functions, import paths). - Place the controller at:
- Page:
<sitePath>/pages/<name>/<name>.ts(or.js) - Part:
<sitePath>/parts/<name>/<name>.ts(or.js) - Layout:
<sitePath>/layouts/<name>/<name>.ts(or.js) - Processor:
<sitePath>/processors/<name>.js
- Page:
Step 6: Generate the View (if applicable)
- For pages, parts, and layouts using Thymeleaf or Mustache, generate a paired
.htmlview file in the same directory as the controller. - For pages and layouts, include
data-portal-region="<region-name>"attributes on container elements. - For region iteration, use
data-th-each="component : ${region.components}"withdata-portal-component="${component.path}".
Step 7: Wire Response Processors (if applicable)
- If generating a response processor, check whether
<sitePath>/site.xmlexists. - If it exists, add a
<response-processor>entry inside the<processors>block. - If it does not exist, create
<sitePath>/site.xmlwith the processor declaration.
Step 8: Update build.gradle Dependencies
- Check the project's
build.gradlefor existing library includes. - Add any missing dependencies:
com.enonic.xp:lib-portal:${xpVersion}— required for all controllers.com.enonic.xp:lib-content:${xpVersion}— if the controller uses content queries.com.enonic.lib:lib-thymeleaf:2.0.0— if using Thymeleaf rendering.com.enonic.lib:lib-mustache:2.1.0— if using Mustache rendering.com.enonic.lib:lib-asset:${libVersion}— if the controller generates asset URLs (replaces the deprecatedportalLib.assetUrlin XP 7.15+).
Step 9: Validate Output
- Verify the descriptor file name matches the parent directory name exactly.
- Verify the controller file name matches the descriptor directory name.
- Verify all region names in the controller/view match those declared in the XML descriptor.
- Read
references/examples.mdto cross-check the generated code against known-good patterns.
Error Handling
- If
scripts/find-enonic-targets.mjsexits with code 1 (NO_PROJECT), inform the user that no Enonic XP project was found and suggest creating the standard directory structure undersrc/main/resources/site/. - If a component with the same name already exists at the target path, warn the user and ask whether to overwrite or rename.
- If the user reports a 404 on a part or missing regions, read
references/troubleshooting.mdto diagnose common causes. - If the generated controller fails at runtime with view resolution errors, verify the view file is co-located with the controller and the
resolve()call uses the correct filename.
Loading...
Select a file to preview
Analyzing security...
Checking scan reports and verification data.
Bill of Materials
Everything this skill can do — files, network, commands, and more.