Feature parity matrix
Mateu’s contract is the wire: any server can serve any renderer. Coverage differs by implementation — this page is the honest snapshot, and the single place to update when something is ported. ✅ full · 🟡 partial (see note) · — not yet.
Servers
Section titled “Servers”The Java server is the reference implementation; the .NET and Python servers emit the same wire
for the surface below (verified by golden-JSON tests in backend/dotnet/test and
backend/python/tests).
| Feature | Java | .NET | Python |
|---|---|---|---|
| Forms, sections, field types, validation | ✅ | ✅ | ✅ |
| CRUD (list / detail / edit / new / save / delete) | ✅ | ✅ | ✅ |
| App shell + menus + navigation | ✅ | ✅ | ✅ |
Wizards (incl. branching, cross-step state, @WizardProgress BAR/STEPS/RAIL) | ✅ | ✅ | ✅ |
CRUD create/edit in a drawer (editInDrawer — save closes + refreshes the listing in place) | ✅ | ✅ | ✅ |
Collection-detail / general-overview archetypes (CollectionDetail<Row>, GeneralOverview<Row>) + fluent FormField | ✅ | ✅ | ✅ |
Guided import wizard (ImportWizard<Row>: CSV upload/paste, auto-mapping grid, validation report, typed import) | ✅ | 🟡 | 🟡 |
| Page decorations (subtitle, banners, badges, KPIs, FABs) | ✅ | ✅ | ✅ |
Header overline + title placeholder (@Overline/@TitlePlaceholder; Java also has OverlineSupplier/TitlePlaceholderSupplier, the ports carry only the declarative form — same as @Subtitle) | ✅ | ✅ | ✅ |
| Tabs, stereotypes, shortcuts, compact, dirty guard | ✅ | ✅ | ✅ |
| Adaptive layout inference (radios, folding, tabs) | ✅ | ✅ | ✅ |
Nav links (@LinkTo / link supplier) | ✅ | ✅ | ✅ |
Route registry (specs/ui/routes.yaml: definition + view model + fixed/default params per route, merged over the derived table). Both ports mirror the model, the matching, the precedence and the definition lookup; neither has a static-bundle exporter, so nothing ships the table to a browser there | ✅ | ✅ | ✅ |
| Dashboard / Foldout / Welcome / ItemOverview archetypes | ✅ | ✅ | ✅ |
| UX components (MetricCard, Gantt, EmptyState, Skeleton…) | ✅ | ✅ | ✅ |
| Planning board (tape chart: resources × days, colored blocks, move/select actions) | ✅ | ✅ | ✅ |
| High-level UX components (Kanban, Timeline, Stat, Calendar, PricingTable, OrgChart, Heatmap, Funnel, TrendChart, FeatureGrid, Testimonials, Faq, CalloutCard, CommentThread, FileList, ComparisonCard, Checklist, ProgressSteps) | ✅ | ✅ | ✅ |
| Front-office components (EntityHeader, Meter, TaskProgress, StatusList, TaskQueue, ResourceGrid, OfferCard incl. toggle state, AddOnPicker, Ledger, PaymentPicker, ProcessMonitor, Notice incl. status/noIcon/content, BulletedList) | ✅ | ✅ | ✅ |
Section polish (@SeparatorBefore, text sizes, @Section(propertyList/frameless), responsive zones) | ✅ | ✅ | ✅ |
Anchor (external links, target + rel=noopener) | ✅ | ✅ | ✅ |
| i18n, events (emit/subscribe), security scaffolding | ✅ | ✅ | ✅ |
Application context selector (@AppContext) | ✅ | ✅ | ✅ |
App header actions (AppActionsSupplier → buttons + dropdown groups) | ✅ | ✅ | ✅ |
@Audience persona projection (audience app-context + projection filter) | ✅ | ✅ | ✅ |
Capture fields (@Signature, @PhotoCapture) | ✅ | ✅ | ✅ |
Generic file upload field (@FileUpload, accept filter in the field attributes) | ✅ | ✅ | ✅ |
Tree selects (@TreeSelect + hierarchical options) | ✅ | ✅ | ✅ |
| Smart-search listing filters (enums as multi-select, date/number ranges) | ✅ | ✅ | ✅ |
Declarative listings (Listing<Row> + capabilities) | ✅ | ✅ | ✅ |
— typed DateRange/NumberRange/Set filter fields | ✅ | ✅ | ✅ |
— DB pushdown (override find: one query, real total, in-memory pipeline skipped) | ✅ | ✅ | ✅ |
Tree lookup selectors (GridLayout.tree + Selector) | ✅ | ✅ | ✅ |
Lookup fields (@Lookup remote combobox + search-<field> action) | ✅ | ✅ | ✅ |
— @Searchable full selector dialogs (Selector + codesearch) | ✅ | ✅ | ✅ |
External REST options (@RestOptions/[RestOptions]/RestOptions() → select; options fetched client-side from an arbitrary endpoint via FormField.optionsSource) | ✅ | ✅ | ✅ |
External REST listing rows (@RestListing/[RestListing]/@rest_listing on a listing → rows fetched client-side from an arbitrary endpoint via Crudl.rowsSource; columns from the Row type) | ✅ | ✅ | ✅ |
External REST button action (@RestAction/[RestAction]/@rest_action on a button → calls an arbitrary endpoint client-side via Action.restAction; response toast + merge into form state) | ✅ | ✅ | ✅ |
External REST screen data (@RestData/[RestData]/@rest_data on a view → initial data fetched client-side on load and merged into the form state; reuses the restAction machinery via a synthetic __restdata__ action + OnLoad trigger) | ✅ | ✅ | ✅ |
— Proxy mode (proxy = true on any of the four → the fetch is routed through the Mateu server via the reserved __restfetch__ action: no CORS, and ${secret.X} auth injected server-side from a secrets provider / env var; the server resolves the DECLARED source only) | ✅ | ✅ | ✅ |
Editable grids / inline CRUD editing (@InlineEditing + update-row) | ✅ | ✅ | ✅ |
Bulk list actions (@ListToolbarButton + typed selection) | ✅ | ✅ | ✅ |
Listing aggregates & grouping (@Aggregate/@GroupBy + summaries) | ✅ | ✅ | ✅ |
Group header actions (@GroupAction buttons on group rows, _groupValue parameter) | ✅ | — | — |
Group summaries synthesized for custom Listings (ListingData.withSynthesizedGroups) | ✅ | — | — |
Optimistic locking (@Version → conflict dialog on save/update-row, _forceOverwrite) | ✅ | ✅ | ✅ |
Notification inbox (NotificationsSupplier → header bell + _notifications-* actions) | ✅ | ✅ | ✅ |
Undoable toasts (Message.undoable → undo action id + parameters on the wire) | ✅ | ✅ | ✅ |
Global entity search (GlobalSearchSupplier → globalSearchEnabled + _globalsearch) | ✅ | ✅ | ✅ |
Dialog/Drawer overlays from actions + closeModal/dispatchEvent | ✅ | ✅ | ✅ |
Structure ETag / template-ref (structureHash + request knownStructureHash → omit the component when unchanged) | ✅ | ✅ | ✅ |
ModelView bindable contract (__contract__ sync action → fields + actions on appData._contract, for the visual-builder tooling) | ✅ | ✅ | ✅ |
Visual-builder live preview (__preview__ sync action → renders arbitrary YAML page text; the plugin’s preview pane) | ✅ | ✅ | ✅ |
YAML pages bound to a ModelView (specs/ui/<route>.yaml with modelView: → the file supplies the layout, the class supplies state + actions; on the classpath in Java, under the cwd — MATEU_SPECS_DIR — in the ports) | ✅ | ✅ | ✅ |
Static-view skip (@StaticView/[StaticView]/@static_view → staticView flag; client caches the full response for the session and skips the round-trip on return) | ✅ | ✅ | ✅ |
Sticky sections index (@Toc) | ✅ | ✅ | ✅ |
Client-side rules (@Hidden(expr)/@Disabled/rule supplier) | ✅ | ✅ | ✅ |
Grid form fields + @OnRowSelected row-click actions (incl. add/create/select on plain forms outside wizards) | ✅ | ✅ | ✅ |
| Wide-field auto-colspan (grid/textarea/richText span the full row of a multi-column section) | ✅ | — | — |
| Inline-editing grid ”+” appends an in-place row (the detail-form response targets a container inline grids never render) | ✅ | — | — |
Multi-state embedded islands (@Inline orchestrator fields, host-seeded initialData) | ✅ | — | — |
Multi-column layouts (@Zones, @FoldedLayout) | ✅ | ✅ | ✅ |
AI chat (@AI/[AI]/@ai → sseUrl; the SSE endpoint is developer-provided) | ✅ | ✅ | ✅ |
| Semantic (composed) annotations | ✅ | ✅ | ✅ (an Annotated alias) |
Federation (remote menus + MicroFrontend islands) | ✅ | ✅ | ✅ |
| Component adapters | ✅ | 🟡 wrapper idiom | 🟡 wrapper idiom |
| Hero search archetype | ✅ | ✅ | ✅ |
Import wizard on .NET/Python: same step flow (upload/paste → auto-mapped column grid with a
select-editable target-field cell → per-line validation report → typed import + result counts)
and the same CSV semantics (,/; autodetect, RFC-4180-ish quoting, data-URI uploads), but
adapted to the ports’ [Step(n)] wizard machinery: the import runs on the validation step’s
Next (the ports’ wizards have no @WizardCompletionAction button — Finish then shows the
summary message), and the validation surface is each port’s own — DataAnnotations ([Required],
[Range]…) on .NET, Required() only on Python (it has no Min/Max markers). Hence the 🟡.
Smart-search filters on .NET/Python: the Crud entity’s fields become the same filter widgets
(enums → multi-select IN, temporals → date ranges, [RangeFilter]/RangeFilter() numerics →
min–max), applied in-memory over Fetch() by default — same as Java’s default repository — or
pushed to the database by overriding Find/find (the filters arrive as the raw component state
rather than Java’s typed FilterCriterion objects; a contract difference, not a capability gap).
Recent .NET/Python parity gains (2026-07-17): CRUD create/edit in a drawer
(Crud<T>.EditInDrawer virtual / @edit_in_drawer decorator — new and row clicks answer the
entity form inside a Drawer Add fragment over the listing; cancel closes it; save persists and
answers CloseModal carrying the mateu-crud:saved-in-drawer event plus a RunAction search
command, so the listing refreshes in place with no navigation), the wizard RAIL progress style
([WizardProgress("rail")] / @wizard_progress("rail") — the step form on the left, a sticky
right band with a big current | total counter over the vertical step list; ProgressSteps
carries vertical in all three backends), and — closing the day’s last gap — the fluent
FormField primitive (a live field composed into any fluent tree, bound to componentState by
fieldId; with options it renders as a select) plus the CollectionDetail and GeneralOverview
archetypes built on it: tree-supplier views seed their scalar properties into initialData (so
search/selection round-trip) and emit an AutoSave trigger so typing/switching re-renders the
page in place.
Recent .NET/Python parity gains (2026-07-11): inline CRUD editing
([InlineEditing]/@inline_editing — editable columns with typed in-place editors +
the update-row action rebuilding and saving the row), lookup fields ([Lookup]/Lookup() →
combobox + remoteCoordinates, the handler answers search-<field> from the options supplier,
filtered and paged), Dialog/Drawer overlays returned from actions (Add fragments on the initiator,
with CloseModal/DispatchEvent command factories carrying {eventName, detail}), [Toc]/@toc,
the full HeroSearch archetype (hero header + cards listing, starts empty), client-side rules
([Hidden(expr)]/[Disabled] + IRuleSupplier/RuleSupplier → ServerSideComponent.rules),
grid form fields (list-of-rows properties → dataType array + stereotype grid + columns) with
[OnRowSelected]/OnRowSelected() injecting the clicked row into the handler method, and the
[Zone]/@zones + [FoldedLayout]/@folded_layout multi-column layouts. Earlier (2026-07-10):
CRUD search sorts and paginates; actions can return page banners, a /route or a UICommand.
Declarative listings (Java Listing<Row> + capabilities / Python Listing[F, R]) landed the same day with the
typed DateRange/NumberRange/Set filters, the _from/_to state assembly, and the
Selector contract on top: @Searchable fields open their selector listing in a modal
(codesearch-<field> → Dialog; row pick → value-changed/data-changed/close-modal-requested),
including TREE-shaped selectors (gridLayout() override → "tree", rows carrying nested
children arrays). Semantic annotations and the AI chat landed too: .NET resolves composed
attributes transitively (Meta.Find, attributes decorating attribute classes) while in Python a
reusable Annotated alias needs no machinery at all; [AI]/@ai emit sseUrl and both manuals
document the SSE endpoint contract (POST {message, sessionId, menuContext?} → data: chunks).
The final gaps closed the same day: DB pushdown (Find/find override — one query with the real
total, the in-memory pipeline skipped), federation ([RemoteMenu]/@remote_menu federated menu
entries — the frontend fetches the remote menu itself — and the MicroFrontend island component),
and component adapters resolved as a documented idiom: both ports render plain classes
reflectively, so a thin wrapper view over the foreign object (fields exposing its data, an action
writing back) replaces Java’s ComponentAdapter SPI — see “Adapting foreign classes” in each
manual. The four depth tails inside ✅ rows closed too: pre-existing @Lookup/@Searchable
values resolve their display label (ILookupLabelSupplier/LookupLabelSupplier →
<fieldId>-label fragment data), grid form fields edit in place (@InlineEditing on the
property, rows binding back into the typed list), permission-driven field states
(@EyesOnly/@ReadOnlyUnless/@DisabledUnless against an adapter-supplied Identity), and the
full @App(AUTO) variant decision table (explicit wins; menu folders via Group/group →
TILES/HAMBURGUER_MENU/MENU_ON_TOP; flat menus → TABS). Nothing on the server surface remains
Java-only.
2026-07-16 parity pass: the front-office dogfooding wave (OfferCard toggle state, StatusItem
avatar, StatusList compact/frameless, Notice status/noIcon/content, @Audience) landed on all
three backends in the same commits; the two features that had slipped through Java-only — app
header actions with dropdown grouping (AppActionsSupplier) and Anchor.target — were ported the
same day (.NET IAppActionsSupplier/Anchor { Target }, Python AppActionsSupplier/Anchor),
each pinned by golden-JSON tests. The remaining Java-only rows above are in-page orchestration
behaviors (embedded islands, inline-grid ”+”, wide-field auto-colspan), not wire surface.
2026-07-17: optimistic locking ([Version]/Version() — stale saves and inline row updates
answer the same reload/overwrite conflict dialog as Java, byte-identical texts; _forceOverwrite
adopts the stored version then bumps) and the notification inbox
(INotificationsSupplier/NotificationsSupplier → AppMetadata.notificationsEnabled +
_notifications-list/_notifications-read with ids list or "all") landed on .NET and Python,
each pinned by golden-JSON tests mirroring the Java sync suites.
Renderers
Section titled “Renderers”Every renderer speaks the same wire; the depth of widget support varies.
| Feature | Vaadin (web) | Redwood (web) | IntelliJ plugin | React Native |
|---|---|---|---|---|
| Forms, CRUD, navigation | ✅ | ✅ | ✅ | ✅ |
| Smart-search filter bar (chips, ranges, multi-select) | ✅ | ✅ | ✅ (native panel) | ✅ panel (ranges, multi-select, date pickers) |
| Sorting, cards/list/tree layouts, empty states | ✅ | ✅ | ✅ (tree = JTree; cards/list adapt to the table) | ✅ |
| Inline editing (@InlineEditing, update-row) | ✅ | ✅ | ✅ (row form) | ✅ (row form) |
| Date picker | ✅ | ✅ | ✅ (calendar popup) | ✅ (own calendar) |
| Remote lookup select (@Lookup / searchable) | ✅ | ✅ | ✅ | ✅ |
| Full field-stereotype set (radio, multiSelect, slider, stepper, stars, color, image upload, money, markdown…) | ✅ | ✅ | ✅ | ✅ |
| Client-side rules (visible/disabled/state) + ${…} interpolation | ✅ | ✅ | ✅ (shared engine) | ✅ (no-eval engine) |
| Page banners (@Banner + action-returned) | ✅ | ✅ | ✅ | ✅ |
| FABs, header badges, KPIs, charts | ✅ | ✅ | ✅ (FABs as header buttons) | ✅ |
| @AutoSave / @SubscribeTo scopes / @OnRowSelected | ✅ | ✅ | ✅ | ✅ |
| AI chat (sseUrl) / theme toggle | ✅ | ✅ | ✅ chat (theme = the IDE’s own) | ✅ |
| App context selector | ✅ | ✅ | ✅ (navigator combos) | ✅ |
| — searchable picker w/ remote search | ✅ | ✅ | 🟡 loaded options only | ✅ |
| Signature capture | ✅ canvas | ✅ canvas | ✅ mouse canvas | ✅ svg + view-shot |
| Photo capture | ✅ getUserMedia | ✅ | 🟡 file picker (no desktop camera API) | ✅ expo-camera |
| Tree select dropdown | ✅ | ✅ | ✅ (JTree popup) | ✅ |
| Tree lookup selector (dialog) | ✅ | ✅ | ✅ (tree layout) | ✅ (tree layout) |
| Dashboards, Gantt, foldouts, skeletons | ✅ | ✅ | ✅ | ✅ |
| High-level UX components (Kanban, Timeline, Stat, Calendar… + the front-office set) | ✅ | ✅ | ✅ | ✅ |
| App header actions (buttons + dropdown groups) | ✅ | ✅ | — (sidebar shell, no top bar) | — (drawer shell, no top bar) |
| Bulk row selection + selection-required toolbar actions | ✅ | ✅ | ✅ (native multi-select) | ✅ (checkbox column) |
| Saved views (named filter sets, default view) | ✅ | ✅ | — | — |
| Column chooser (per-user show/hide/reorder) | ✅ | ✅ | — | — |
| Listing totals footer + group subtotal rows | ✅ | ✅ | ✅ | ✅ |
| Notification bell (inbox, unread count) | ✅ | ✅ | ✅ (sidebar popup) | ✅ (drawer row) |
| Undoable toasts (Undo button) | ✅ | ✅ | ✅ (balloon action) | ✅ (toast button) |
| Entity search (GlobalSearchSupplier: ⌘K palette / search box) | ✅ palette | — (own shells render no palette yet) | ✅ sidebar search | ✅ drawer search |
| Planning board (tape chart) | ✅ drag+select | ✅ | 🟡 read-only (no drag) | 🟡 read-only (no drag) |
Session-expiry re-auth + retry (onSessionExpired) | ✅ | ✅ | — | — |
| Dockable multi-tab workspace | — | — | ✅ (IDE editor tabs/splits) | — |
| App registry boot (installable → registry → backend) | — | — | ✅ (+ min IDE build gate) | ✅ |
Since 2026-07-12 (DS-native rule) the non-Vaadin web renderers render crud layouts (table/list/cards/masterDetail/tree), toolbar buttons and grid-stereotype form fields with their OWN design-system components, and since 2026-07-16 the shells render the app header actions (plain buttons + dropdown groups) with their own widgets too.
MessageList/MessageInput (Vaadin): as of 2026-07-10 these carry a real data model
(List<MessageListItem> / an actionId that fires on submit) — they were previously stubs that
rendered hardcoded demo data.
Retired renderers (2026-08-12 reconciliation). SAP UI5, Redwood-OJ (OJET), Red Hat/PatternFly
and SLDS were retired: apps/sapui5, apps/redhat and apps/slds hold only leftover dist/
output, with no sources and no package.json. They had a column here long after they stopped
existing — which is the worst failure mode for this page, since a matrix that promises a renderer
nobody can use is worse than one that admits a gap. The supported web renderers are Vaadin and the
Redwood/VB line.
frontend/app/vscode-extension is not a renderer: it hosts the visual editor (the same web
bundle the IntelliJ JCEF host runs), so it belongs with the tooling, not in this table.
Update this page whenever parity moves — it is referenced from the language manuals and the Rosetta.