Skip to content

IDE tooling: IntelliJ and VS Code

Both IDE integrations author the same specs/ui/** files and share their file skeletons, so a team can mix editors freely.

IntelliJ pluginVS Code extension
Schema validation + completion for specs/ui/** YAML✅ bundled specs schema✅ yamlValidation (needs the Red Hat YAML extension)
Visual editor (palette, canvas, properties)✅ JCEF editor tab✅ custom editor
Redwood canvas (the real Oracle VB renderer, editable)✅ served by the plugin✅ served by the extension
New file from a template (mount, routes, app shell, sources, pages)✅ New | Mateu✅ Mateu: New File…
Add a route to a routes file (and set the mount’s home)✅ Add Mateu Route…✅ Mateu: Add Route…
Binding checks against the Java view model (+ quick fixes)✅—
Runs the Mateu app inside the IDE✅ (native renderer)—
Per-project backend + authentication✅ Settings | Tools | Mateumateu.baseUrl setting

IntelliJ needs a Java IDE (IntelliJ IDEA Community or Ultimate): the binding checks resolve view models through the Java plugin.

The visual editor’s canvas: Vaadin or Redwood

Section titled “The visual editor’s canvas: Vaadin or Redwood”

Both editors can paint the canvas with the Vaadin renderer or with the real Redwood renderer, which is the Oracle Visual Builder app of io.mateu:mateu-redwood. The canvas opens in the project’s renderer (project.yaml, below), and the selector in the editor’s toolbar previews the other renderer for the session. See the Redwood canvas. In both IDEs the Redwood app is part of the editor’s bundle. The IDE’s local server serves it, so it works with no backend running. VS Code frames it from the extension’s loopback server, because a webview cannot host the app itself. A bundle built without the Redwood app falls back to the configured backend’s own (/_index.html, /_redwood/). In every case Redwood loads Oracle JET and the Visual Builder runtime from Oracle’s CDN, so the IDE needs to reach static.oracle.com. Without it the canvas shows a notice instead of the page, and the Vaadin canvas keeps working offline.

The renderer is a project setting, kept in specs/ui/project.yaml (type: Project, renderer: vaadin | redwood; see project settings). Both IDEs edit that file, and the file is the source of truth:

  • IntelliJ: Settings | Tools | Mateu → Project → Renderer reads project.yaml when the page opens and writes it on Apply. It creates the file if it is missing and rewrites only the renderer: line.
  • VS Code: the mateu.renderer setting follows the file. It is synced from the file on activation and whenever the file changes, and changing the setting writes the file. The command Mateu: Project Settings… asks for the renderer and writes the file too.
  • New | Mateu → Project Settings creates the descriptor. It is offered only while the project has none, because there is one per project.
  • The UI Mount wizard shows the project’s renderer and the artifact the app must depend on (io.mateu:mateu-vaadin or io.mateu:mateu-redwood).

The visual editor’s canvas, Play and Export use this renderer. The canvas’s own toolbar switch is only a preview for the session.

Right-click a folder in the Project view (or press ⌘N / Alt+Insert on it) and pick New | Mateu. In VS Code, right-click a folder in the Explorer and choose Mateu: New File… (also in the command palette). Every kind of file under specs/ui is offered:

EntryCreatesNotes
UI Mounttype: UIAn app served at a base path — the data-driven @UI. Lists its route files. Optionally names its home page route (home:, the page the mount opens on — see the mount’s home) — usually left empty at creation and set later from Add Route….
Routes Filetype: RoutesCreated empty (routes: [] under a short header pointing at the route registry). Pick the mount (type: UI) to register it in — it is appended to that mount’s routes: list (preselected when there is exactly one). The optional base path is only for a class-declared @UI("/shop") mount. Add the entries one at a time with Add Route… (below).
App Shelltype: AppShellTitle, variant, home route and a menu with a group. Bind it to the mount root ("").
Action Cataloguetype: ActionsCreated empty (actions: [] under a short header). Named flows and REST calls the shell menu and any page run by id — see the action catalogue. The visual editor opens it in a structured editor (add / rename / describe / remove actions, edit their steps), and every action-id picker offers its ids marked catalog.
REST Source Cataloguetype: SourcesTwo example sources (source: nested, provenance, fields, totalPath). See the REST source catalogue.
Page…a page definitionPick a template and a page width (below). When the folder has a routes file, Add a route to <routes file> (on by default) appends a route to the new page, named after the file — optionally making it the home page.

Page templates follow the page templates Mateu ships:

TemplateRootDefault width
FormForm with a FormLayout and Save / Cancelfixed
Listing / CRUDListing over a named source, filters, New, rowRoute to the recordfull width
Wizard stepForm with progress and Back / Nextfixed
DashboardScoreboard of MetricCards over a DashboardLayoutfull width
Smart Searchintro line + searchable Listing with filtersfull width
To-do ListTaskQueue of counted bucketsfixed
Calendartoolbar + Calendar (month/week/day/list)full width
WelcomeHeroSection with calls to action + tilesfixed
Hero SearchHeroSection + Listing as cardsfixed
Collection Detailitem list left, detail (empty state) rightfull width
General Overviewrecord switcher + EntityHeader + cardsfull width
Item Overviewsticky key-info card + TabLayoutfull width
FoldoutFoldoutLayout with panelsedge to edge
Gantt Pagetitle + Ganttedge to edge
Data Managementgrid ⇄ Gantt tabsfull width
Matrix GridMatrixGrid with sections, editable rowedge to edge
Planning BoardPlanningBoard resources × daysedge to edge
Blank layoutan empty VerticalLayoutrenderer decides

The page width (fixed = centred, max 1408px · full width = 24px gutters · edge to edge = no margins) is written as the root layout’s style, because a YAML definition has no pageWidth key; choose Let the renderer decide to leave it out.

Where the file goes. If you right-clicked a folder inside specs/ui, the file goes there. Otherwise the nearest existing specs/ui (src/main/resources/specs/ui or specs/ui) at or above that folder is used; failing that, src/main/resources/specs/ui is created when the folder is a Maven/Gradle module, else <folder>/specs/ui. Existing files are never overwritten.

Every skeleton is validated against the generated specs schema in the plugin’s test suite (strictly: a key the schema does not declare fails), so a new file never starts out red. In IntelliJ the skeletons are ordinary file templates — customise them in Settings | Editor | File and Code Templates | Other (Mateu … entries). Placeholders: __TITLE__, __NAME__, and a line holding only __PAGE_WIDTH__.

A route registry grows one entry at a time. In IntelliJ, right-click a type: Routes file in the Project view or inside its editor and choose Add Mateu Route… (also under New | Mateu › Route… when the folder has a routes file). In VS Code, run Mateu: Add Route… from the Explorer or editor context menu of the routes file, or from the command palette. You choose:

FieldWritten asNotes
Routes file—Preselected when invoked on one; a choice when the specs folder has several.
Layoutlayout:A page or app shell discovered under specs/ui (relative to it), or none when the view model supplies its own tree. layout is the canonical key (definition is its deprecated alias).
Routeroute:Relative to the mount; empty is the mount root (typically the app shell). Defaults to the layout’s file name in kebab case. A route already declared in the file is rejected.
View modelviewModel:Optional fully qualified class — empty is a definition-only route, which is valid (the statically served case).
Parent routeparent:Optional: one of the file’s existing routes; the new route renders in that screen’s slot (the route stays absolute).
Make this the home pagehome: in the mountSets (or replaces) the home: route of the type: UI mount that lists this routes file, and shows the current one. Disabled when no mount lists the file.

Every change is a minimal text edit: the entry is appended after the last one (the first one turns routes: [] into a block list), the mount gets one new line, and nothing else in your files is reformatted. Fixed/default parameters, children and the data scopes are then edited by hand — see the route registry.

Connecting IntelliJ to a backend: Settings | Tools | Mateu

Section titled “Connecting IntelliJ to a backend: Settings | Tools | Mateu”

The plugin stays out of projects that are not Mateu apps: with no backend configured it makes no HTTP calls, shows no Mateu tool windows or toolbar widget, and never touches the window title. Configure a project in Settings | Tools | Mateu (stored in .idea/mateu.xml):

  • Base URL of the backend (e.g. http://localhost:8080) and the start route; or an app registry URL + app id, which resolves the base URL and launch parameters.
  • Authentication:
    • Bearer token — pasted once, kept in the IDE credential store (Keychain, KWallet, KeePass…), never in the project; sent as Authorization: Bearer on every Mateu call.
    • OpenID Connect (device sign-in) — issuer + client id (endpoints are discovered, or set explicitly). Sign In… shows a code and opens your browser; the refresh token is kept in the credential store and access tokens are refreshed silently.
  • A 401 first tries a silent refresh; otherwise one notification offers Sign in… / Open settings, and the request is retried once with the new credentials.

JVM system properties override the settings, for CI or a one-off run: -Dmateu.baseUrl, -Dmateu.route, -Dmateu.registryUrl, -Dmateu.appId, -Dmateu.token; -Dmateu.debug=true logs the wire traffic.

The standalone desktop distribution (the IDE rebranded as your app, see Desktop & Mobile) is the only place the plugin takes over the frame title, hides foreign tool windows and lands on the home route.

Run | Run Mateu App (Live) (also under Tools) starts the project’s app in development mode (mateu.dev=true, every src/main/resources/specs/ui of the project watched) with the debug agent listening, attaches a Remote JVM Debug session once it answers, points Settings | Tools | Mateu at it when nothing else is configured — so this tool window and the visual editor’s Play use the running app — and opens it in the browser. From then on a YAML edit (in the text editor or the visual editor’s canvas) re-renders the open screen in place, and every HotSwap fires POST /mateu/dev/reload so the screen shows the new code. Run | Reload Mateu Screen fires it by hand. Spring Boot, Quarkus, Micronaut and Helidon apps (Maven or Gradle) are detected. VS Code has the same pair: Mateu: Run App (Live) and Mateu: Reload Screen (also fired on a Java hot code replace). Details, adapters and limits: Live reload.