Skip to content

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.

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).

FeatureJava.NETPython
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 (GlobalSearchSupplierglobalSearchEnabled + _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_viewstaticView 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]/@aisseUrl; 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/RuleSupplierServerSideComponent.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/NotificationsSupplierAppMetadata.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.

Every renderer speaks the same wire; the depth of widget support varies.

FeatureVaadin (web)Redwood (web)IntelliJ pluginReact 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.