cx-composer
# ────── how it works ──────

From zero to a deployable Client Extension.

The story, the workflow, and the interactive demo — how CX Composer turns writing-yaml-from-memory into a wizard-driven, IntelliSense-guided flow.

# ────── how it works ──────

From zero to a deployable Client Extension in three steps.

    01

    Scaffold from a wizard.

    Pick one of the 28 Client Extension types, answer the required prompts, and get a working project — yaml, code, Dockerfile, LCP.json, all schemas verified against Liferay's own reference samples.

    step 01
    ❯ CX Composer: Scaffold New Project
      ▸ Object Action  (microservice · backend)
      ▸ Custom Element (frontend)
      ▸ Site Initializer (batch)
      … 25 more
    02

    Author with schema-aware IntelliSense.

    Completions, hover docs, and did-you-mean diagnostics on client-extension.yaml. Full schema IntelliSense on batch/*.batch-engine-data.json across all 309 registered Liferay entity types.

    step 02
    type: |
      ┌ customElement     web component
      │ objectAction      microservice
      │ batch             batch-engine
      └ …25 more
    03

    Validate + build without leaving the editor.

    Six layered validators catch mistakes before deploy — unknown fields, missing OAuth scopes, missing companion files, invalid token definitions, missing parent-FK on batch data. Then blade builds the zip per-extension.

    step 03
    ✗ Unknown field "instanceableq" on customElement
      did you mean "instanceable"?
    
    ✓ BUILD SUCCESSFUL in 3.2s
      → build/my-widget-1.0.0.zip
# ────── the pain we remove ──────

Ship a Liferay microservice in 10 seconds instead of 45 minutes.

A working Object Action needs a yaml block, a paired OAuth application, an Express handler, a `package.json`, a Dockerfile, an LCP.json, and a folder tree that exactly matches Liferay Cloud’s expected paths. CX Composer scaffolds all of it from one command.

without cx-composer~ 45 minutes
  1. 01Cross-reference the yaml schema for objectAction5 min
  2. 02Copy a sample OAuth app block, edit ref codes5 min
  3. 03`npm init`, install Express + JWT deps by hand10 min
  4. 04Write a Dockerfile matching Liferay Cloud runtime5 min
  5. 05Wire the resourcePath into your handler route2 min
  6. 06Compose LCP.json with the right ready-probe port3 min
  7. 07Deploy, hit a validation error, edit yaml, repeat15 min
7 chances to typo an OAuth ref code or misalign a Docker port
with cx-composer~ 10 seconds
❯ cx-composer scaffold objectAction --with-code=ts
✓ my-action/
  client-extension.yaml // action + paired oauth-agent, no typos
  app.ts, config.ts, util/*.ts
  package.json, tsconfig.json
  Dockerfile // FROM liferay/node-runner:latest
  LCP.json // /ready probes on the right port
❯ blade gw buildClientExtensionZip
→ build/my-action.zip
0 hand-edits · runs on the real Liferay Cloud runtime image
# ────── 60 seconds after install ──────

What you can do in a minute.

Install, open a Liferay workspace, and start scaffolding. No config, no gradle changes, no login for the free tier.

  • Scaffold a Node.js Object Action with paired OAuthyaml + app.js + Dockerfile + LCP.json
    10s
  • Add a Custom Element with a Liferay Headless callJS + CSS + Liferay.authToken wiring
    15s
  • Validate every yaml in a monorepoauto-runs on save, or right-click a folder
    5s
  • Catch a bad OAuth cross-reference before deployflagged inline against the Problems panel
    live
  • See which CX .zip is stalesidebar tree with built / stale / not built badges
    auto
  • Scaffold a Site Initializer that deploys cleanlayouts, master pages, fragments, style-books, roles
    20s
  • Bundle a JS Import Map Entry with webpackcontenthash-safe URL, output to build/static
    10s
  • Author a frontend token definition without guessingschema-validated on save, matches Liferay 2024.Q2+
    live
# ────── why ──────

Built by Liferay developers for Liferay developers.

01
Every feature came from a real pain.

Scaffold flows, folder validators, auto-paired OAuth, the workspace tree — each one exists because we hit the same friction while shipping Client Extensions ourselves. If it saves you 30 minutes on a real day, it earned its keep.

02
Free covers the fastest CX types.

Validation is free for the four static-asset CX types you iterate on most — globalJS, globalCSS, themeSpritemap, jsImportMapsEntry — plus LCP.json and Dockerfile. Pro extends deep validation to every backend, theme, and site-initializer CX type.

03
Match Liferay's own conventions.

Every scaffold is modelled on Liferay's official reference samples — Node.js/TypeScript for microservices, vanilla Web Components for Custom Elements, the site-initializer-masterclass folder tree. Liferay itself doesn't require these languages (bring any stack you want) — we picked them for zero-build-step deployability and minimal runtime dependencies. Deploys clean on the real runtime.

❯ install freeVS Code Marketplace →JetBrains Marketplace →·independent third-party product · not affiliated with Liferay, Inc.
# ────── in the editor ──────

Scaffold any of 28 Client Extension types — right from the palette.

Trigger from the command palette or the sidebar. Filter with the same fuzzy match VS Code uses everywhere else. Hit ↵ on a type to see its docs.

~/my-liferay-workspace
Scaffold Client Extension — choose type
❯28/28
CX ComposerProLiferay 7.4
❯$ nvim client-extension.yaml# try me — completions + hover work here just like in VS Code
client-extension.yaml — [+] modified
Loading editor…

-- INSERT -- place cursor inside my-widget: and start typing.

or type type: on a new line — dropdown lists every CX type.

# ────── product faq ──────

Product FAQ

  • What is CX Companion?
    CX Companion is the AI panel inside CX Composer — a workspace-aware chat available in VS Code and every JetBrains IDE. You describe what you want to build in plain English and CX Companion picks the right Liferay Client Extension type, scaffolds the full project (yaml, paired OAuth block, Dockerfile, assemble block, handler stub), edits existing yaml files, and runs the full preflight validator on every change. Nothing writes to disk until you review and accept each change — every file edit lands in a pending-edits review queue. CX Companion also hosts the **Website → Batch Client Extension** migrator: paste a URL, the plugin crawls the site, uses AI to infer an Object Definition schema from the extracted content, pulls records out as Object Entries, and produces a ready-to-deploy batch CX folder. CX Companion is Pro-only and currently in Preview. You bring your own AI key — Anthropic, OpenAI, Google, Groq, Azure, Ollama, or any OpenAI-compatible endpoint — and CX Composer calls the provider directly from your IDE; keys stay in the OS keychain and prompts never pass through cxcomposer.dev.
  • Does CX Composer have AI?
    Yes — CX Companion is CX Composer's built-in AI panel for Liferay Client Extensions, available in VS Code and JetBrains IDEs. It scaffolds complete client extensions from a plain-English prompt ("I need to run a logic once an object entry is created" → full objectAction with paired oAuthApplicationUserAgent, Dockerfile, assemble block, handler stub), edits existing yaml, auto-pairs the required OAuth block for every microservice-paired type, and runs preflight validation on every proposed change before you see it. Nothing writes to disk without your explicit Accept — every file edit queues up in a review panel first. BYO AI key: Anthropic, OpenAI, Google, Groq, Azure, Ollama, or any OpenAI-compatible endpoint (OpenRouter, Together, LM Studio, your own gateway). Pro, Preview.
  • Is CX Companion safe to use on real workspaces?
    Yes — the whole point of the design is to keep AI changes under your control. Three safeguards: (1) **pending-edits review queue** — every file write stages as a diff in a side panel; nothing hits disk until you click Accept on that specific row, (2) **preflight validation on every proposal** — before you see a staged edit, CX Companion runs the plugin's full yaml validator against it, so broken shape / missing required fields / orphaned OAuth references appear as warnings on the review row, and (3) **cross-block OAuth pairing checks** — a scaffolded microservice always ships with its paired oAuthApplicationUserAgent or oAuthApplicationHeadlessServer, never alone. CX Companion also stops streaming the moment it stages edits, so the chat doesn't race ahead while you're reviewing. Chat scope is restricted to Liferay Client Extensions (polite redirect for off-topic asks).
  • What is a Liferay Client Extension?
    A Liferay Client Extension is a declarative package — defined by a client-extension.yaml manifest — that extends a Liferay DXP install without deploying a portlet or an OSGi bundle. There are 28 types spanning frontend widgets (Custom Element, IFrame), theming (Theme CSS, Global CSS/JS), configuration (OAuth apps, Instance Settings), microservices (Object Action, Workflow Action, Notification Type, CAPTCHA), batch (Batch, Site Initializer), commerce (Payment / Checkout / Shipping / Tax), and audiences. Each extension is built into a .zip with blade gw buildClientExtensionZip and deployed to a Liferay server.
  • Is there a Liferay Client Extension code generator?
    Yes — CX Composer is a Liferay Client Extension code generator available as a **VS Code** extension and an **IntelliJ IDEA / JetBrains Platform** plugin (WebStorm, PhpStorm, PyCharm, GoLand, RubyMine, RustRover, DataGrip). It generates the client-extension.yaml manifest plus all the working code the extension needs: for microservice CX types (Object Action, Workflow Action, Notification Type, CAPTCHA, Commerce) it generates a Node.js or TypeScript Express handler, package.json, two-stage Dockerfile, LCP.json with liveness/readiness probes, and the paired OAuth application entry. For Site Initializer it generates the full folder tree Liferay expects (layouts, master pages, fragments, taxonomies, style books, object definitions, roles, notification templates). For Theme CSS it generates a starter frontend-token-definition.json. For Batch, right-click a batch CX folder → **Add Batch File** wizard lets you pick from **309 registered Liferay entity types** and drops a schema-correct batch/<entity>.batch-engine-data.json skeleton with the correct configuration.className, envelope shape, and required fields prepopulated. All schemas are verified against Liferay's official reference samples and DTO schemas extracted from Liferay's public OpenAPI schemas, so generated projects deploy against DXP without further tweaks.
  • Does CX Composer validate batch Client Extensions?
    Yes — with full schema coverage for **every one of Liferay's 309 registered batch-engine entity types** (Object Definitions, User Accounts, Sites, Taxonomies, Blog Postings, Workflow Definitions, Commerce entities, and 300 more). Schemas were extracted from Liferay's public OpenAPI schemas and enriched with 169 hand-verified runtime patches for parent-FK relationships that OpenAPI omits (e.g., Region.countryId, TaxonomyCategory.parentTaxonomyVocabularyExternalReferenceCode). Inside batch/*.batch-engine-data.json, CX Composer offers auto-complete for the configuration.className (all 309 entities, grouped and filterable), field completions inside items[] tailored to the file's specific className, hover documentation for every field pulled from Liferay's schema, and real-time diagnostics that catch missing required fields *before* you deploy — no more "No Country exists with primary key 0" errors after blade gw buildClientExtensionZip.
  • What is CX Composer for Liferay?
    CX Composer is a VS Code extension **and IntelliJ IDEA plugin** that provides the full authoring lifecycle for Liferay Client Extensions: multi-step scaffolding for all 28 types (including full working Node.js or TypeScript microservices with Docker, and a complete Site Initializer folder tree), IntelliSense on client-extension.yaml (completions + hover for every field on every type), full schema IntelliSense + validation for **all 309 registered Liferay batch-engine entity types** inside batch/*.batch-engine-data.json, a workspace view listing every CX with deploy status, per-extension build via Blade, and six layered validators. Free tier validates LCP.json, Dockerfile, and yaml for four static-asset CX types (globalJS, globalCSS, themeSpritemap, jsImportMapsEntry). Pro (from $5/month, or $25/year) extends validation to every other CX type — including the full 309-entity batch surface — and unlocks the full productivity suite plus AI-powered scaffolding.
  • Does it scaffold real microservices for Object Actions, Workflow Actions, and similar types?
    Yes. For Object Action, Workflow Action, Notification Type, Object Validation Rule, Object Entry Manager, CAPTCHA, and every Commerce integration, choose "With code" and pick Node.js or TypeScript. You get an Express handler mounted at the resourcePath you entered, a package.json, a two-stage Dockerfile, and — the piece nobody remembers — the paired oAuthApplicationUserAgent entry auto-declared in the same yaml with matching naming (<id>-oauth-agent). Batch and Site Initializer get a paired oAuthApplicationHeadlessServer instead (named <id>-oauth-server).
  • What languages does the scaffolder use, and am I locked into them?
    For microservice CX types (Object Action, Workflow Action, Notification Type, Object Validation Rule, Object Entry Manager, CAPTCHA, and every Commerce integration) the scaffolder generates a **Node.js or TypeScript** Express handler. For Custom Element CX types it generates a **vanilla Web Component** — plain ES module, class extends HTMLElement, no framework runtime. Liferay does **not** restrict what language or framework you use. A microservice CX just needs an HTTP endpoint listening on resourcePath; a Custom Element just needs a JS bundle that registers a custom-element tag. If you'd rather build your CX in Java/Spring, Go, Python, Deno, Bun, or with a frontend framework like React, Vue, or Svelte — that's fully supported by Liferay. CX Composer's IntelliSense, validation, and Blade build all still work regardless of what you write inside. We chose Node.js/TypeScript + vanilla Web Components as the scaffold defaults because they (1) deploy with zero or minimal build step, (2) mirror Liferay's own reference samples (liferay-sample-etc-node, liferay-sample-custom-element-4), (3) keep runtime dependencies minimal — no framework runtime bundled per widget, no migration risk when a JS framework changes major versions, and (4) play cleanly with Liferay's SPA navigation lifecycle. It's a simplicity choice — not a Liferay constraint.
  • Does it scaffold a working Site Initializer folder tree?
    Yes. Choose Site Initializer with "With code" and CX Composer generates the full tree — layout-set/public/metadata.json, layouts/01_home/page.json + page-definition.json, layout-page-templates/master-pages/main/, fragments scoped under fragments/group/, taxonomies, style books, object definitions, roles, navigation menus, and a notification template. Every filename and field name is verified against Liferay's liferay-aicontentwizard-site-initializer and site-initializer-masterclass samples, so it deploys cleanly on the first try.
  • Can I see all client extensions in a workspace at once?
    Yes. The **Extensions in Workspace** sidebar panel lists every client-extension.yaml in your workspace, each row showing extension count, deploy status (built if a .zip in build/ is newer than all sources, stale if sources are newer, not built if no zip exists), and last-modified time. Click a row to open its yaml; hover for one-click build or validate. Auto-refreshes when files change.
  • How does CX Composer compare to Blade CLI?
    Blade CLI is a general-purpose Liferay tooling CLI — it can generate module skeletons, deploy bundles, and drive Gradle. CX Composer complements Blade with editor-first workflows: it invokes Blade under the hood for build (buildClientExtensionZip) but adds IntelliSense, validation, and a wizard-driven scaffold that Blade does not provide.
  • Do I need a Liferay Workspace?
    For scaffolding, add-extension, and validation — no, CX Composer works on any folder. For building (Build command), yes: you need a Liferay Workspace with the workspace Gradle plugin so Blade's buildClientExtensionZip task is available.
  • What files does CX Composer validate, and what's free vs Pro?
    Six layered validators, all auto-running on save/open: (1) client-extension.yaml — full schema for all 28 types, unknown fields flagged with did-you-mean; (2) LCP.json — Liferay Cloud service config; (3) Dockerfile — instruction ordering + deprecation warnings; (4) folder-level companion checks — missing Dockerfile / assemble source / referenced JSON; (5) smart frontend-token-definition.json — walks up from the JSON to find its themeCSS entry and enforces the full frontendTokenCategories → sets → tokens → mappings schema; (6) **batch/*.batch-engine-data.json** — schema IntelliSense + validation against all **309 registered Liferay batch-engine entity types**, with 169 hand-verified runtime FK patches so imports don't fail with "No X exists with primary key 0". **Free tier:** LCP.json, Dockerfile, and yaml validation for the four static-asset CX types most projects iterate on — globalJS, globalCSS, themeSpritemap, jsImportMapsEntry. **Pro tier** ($5/month, $15 every 6 months, or $25/year): yaml validation for the other 24 CX types (all microservice / backend types, themeCSS, Site Initializer, Batch, Commerce), folder-level companion checks, cross-reference validation, deep frontend-token-definition.json shape checking, and the full 309-entity batch schema surface.
  • Is CX Composer affiliated with Liferay?
    No. CX Composer is an independent third-party product. Liferay® and Liferay DXP® are registered trademarks of Liferay, Inc. See https://cxcomposer.dev/legal for details.
  • What Liferay DXP versions does CX Composer support?
    CX Composer's schema targets Liferay DXP 2024.Q1+ and Liferay Portal GA100+. Field additions from later releases (globalJS scope/scriptLocation, globalCSS scope) are supported. The Client Extension format has been stable since DXP 2023.Q4.

See it end-to-end.

Ready for the concrete capability list? Every one of the seven features has a live demo and a copy-pasteable command.