Skip to content

App Annotations

Target: TYPE

The primary annotation. Registers a class as a UI endpoint and mounts it at the given route path. Every Mateu application needs at least one @UI-annotated class.

public @interface UI {
String value(); // required: route path e.g. "/orders"
String indexHtmlPath() default "/static/_index.html";
String frontendComponentPath() default "/assets/mateu.js";
}
AttributeTypeDefaultDescription
valueString—URL path at which this UI is mounted
indexHtmlPathString"/static/_index.html"Path to the HTML shell served for this UI
frontendComponentPathString"/assets/mateu.js"Path to the compiled frontend component
@UI("/home")
@Title("My first Mateu app")
public class Home {
@NotEmpty
String name;
@Button
public Message greet() {
return new Message("Hello " + name);
}
}

Marks a class as the application shell and selects its navigation layout variant.

public @interface App {
AppVariant value() default AppVariant.AUTO;
AppLayout layout() default AppLayout.SINGLE_SLOT;
boolean themeToggle() default false;
String accentColor() default "";
String accentStrip() default "";
int accentStripSeed() default 7;
}
AttributeTypeDefaultDescription
valueAppVariantAUTONavigation layout variant for the shell
layoutAppLayoutSINGLE_SLOTContent area layout (SINGLE_SLOT or SPLIT)
themeTogglebooleanfalseShows a moon/sun icon button in the header to switch dark/light mode (ignored by the Redwood renderer, which is light only)
accentColorString""The app’s brand accent (a CSS colour). Not the primary colour: see below
accentStripString""The accent strip’s image (a URL, repeated along it); blank = a strip Mateu draws from the accent; "none" = a plain band in the accent colour (Vaadin renderer)
accentStripSeedint7The seed of the generated strip: another seed, another drawing in the same palette
backLinkBackLinkBREADCRUMBSPARENT draws a single «← Parent» link (labelled with the title of the nearest screen above the app’s route) and drops the breadcrumb trail inside the app — the console style for a record master

An @App with no menu of its own that answers a routes.yaml route with children offers those children as its options — the tabs of a record master. See the recipe.

AppVariant values:

ValueDescription
HAMBURGER_MENUCollapsible hamburger-style navigation drawer. (HAMBURGUER_MENU, the old misspelling, still works but is deprecated.)
MENU_ON_LEFTPersistent navigation panel on the left side
MENU_ON_TOPNavigation bar along the top
TABSTab-based navigation
TILESFlat top-level nav; items with children open a tiles hub in the content area
RAILCompact icon rail on the left side
AUTOFramework picks the variant from the menu shape (see below)
MEDIATORUsed for nested sub-applications acting as a mediator

With AUTO (the default), the variant is inferred from the menu: a menu that federates a RemoteMenu → MENU_ON_TOP; if any top-level item has grandchildren (menu depth > 2) → TILES; more than 7 top-level items → HAMBURGER_MENU; otherwise MENU_ON_TOP. An app with no submenus at all renders as TABS, however many items it has. See Navigation & Menus for the full behaviour of each variant.

AppLayout values:

ValueDescription
SINGLE_SLOTStandard single-content-area layout (default)
SPLITContent area split into two panes
@UI("/app")
@App(AppVariant.HAMBURGER_MENU)
public class ShellApp { ... }

Set themeToggle = true to show a moon/sun icon button in the application header. Clicking it switches between dark and light mode and persists the choice in localStorage. On first load the stored preference is applied; if no preference is stored the OS prefers-color-scheme media query is used as the default.

The Redwood renderer is light only: it ignores themeToggle (no switch in its header) and always paints the light theme, whatever the OS prefers or a stored choice says. The same app class served by the Vaadin renderer keeps its switch.

@UI("/app")
@App(value = AppVariant.AUTO, themeToggle = true)
public class MyApp { ... }

accentColor gives the shell the app’s brand colour, for example @App(accentColor = "#D2232A"). It is kept separate from the theme’s primary colour on purpose. Primary means “you can click this”, and the accent never does. The Vaadin shell uses it in these places:

  • the accent strip, drawn where Redwood draws its colour strip rather than fixed under the header: under a page’s header, on top of a listing’s results and at the foot of the welcome hero. By default Mateu draws it from the accent, a Redwood-style band in a palette derived from the colour (accentStripSeed picks the drawing). accentStrip can name the app’s own image instead (for example @App(accentColor = "#464c68", accentStrip = "/images/strip.svg")), repeated along the strip, or say "none" for a plain band in the accent colour. See Accent colour and strip. The Redwood renderer keeps its own Spectra strips;
  • the welcome hero’s background, a deep tone of the accent;
  • the console name in the menu band, in the light theme only. In dark mode the name stays in the header text colour, because a brand red loses contrast on the dark base.

With no accent there is no strip. The values reach the page as custom properties on mateu-app (--mateu-accent, --mateu-page-band-h, --mateu-page-band-image; the hero also reads --mateu-hero-background), which an app’s own CSS can also set.


Target: TYPE

Sets the browser tab title (<title> element in the HTML).

public @interface PageTitle {
String value();
}
@UI("/orders")
@PageTitle("Orders – My App")
public class OrdersPage { ... }

Target: TYPE

Sets the visible heading rendered inside the page, above the content area.

public @interface Title {
String value();
}
@UI("/home")
@Title("My first Mateu app")
public class Home { ... }

@Title controls the heading inside the page UI. @PageTitle controls the browser tab. Both can be combined.


Target: TYPE

Sets a subtitle displayed below the page title.

public @interface Subtitle {
String value();
}
@UI("/products")
@Title("Product Catalog")
@Subtitle("Browse and manage all products")
public class ProductCatalog { ... }

Target: TYPE

Sets the URL of the image displayed as the application logo in the header or navigation drawer.

public @interface Logo {
String value(); // URL or path to the logo image
}
@UI("/_workflow")
@Logo("/images/logo.svg")
public class WorkflowHome { ... }

Target: TYPE

Sets the browser favicon for the UI.

public @interface FavIcon {
String value(); // URL or path to the favicon
}
@UI("/_workflow")
@FavIcon("/images/favicon.ico")
public class WorkflowHome { ... }

Target: TYPE

No attributes. Starts the navigation drawer in the closed (collapsed) state when the page is first loaded.

@UI("/app")
@App(AppVariant.HAMBURGER_MENU)
@DrawerClosed
public class ShellApp implements App { ... }

Target: TYPE

Integrates Keycloak authentication. The frontend will redirect unauthenticated users to the Keycloak login page before the UI is displayed.

public @interface KeycloakSecured {
String url();
String realm();
String clientId();
String jsUrl() default "";
}
AttributeTypeDefaultDescription
urlString—Keycloak server base URL
realmString—Keycloak realm name
clientIdString—Keycloak client ID
jsUrlString""Optional override for the Keycloak JS adapter URL
@UI("/_workflow")
@KeycloakSecured(
url = "https://auth.example.com",
realm = "myrealm",
clientId = "my-app"
)
public class WorkflowHome { ... }

Target: TYPE

Points to a YAML file that describes the UI declaratively instead of (or alongside) Java annotations.

public @interface UISpec {
String value(); // path to a YAML UI spec file
}
@UI("/dashboard")
@UISpec("/specs/dashboard.yaml")
public class Dashboard { ... }

Target: TYPE

Enables an AI assistant sidebar for the UI by wiring it to a Server-Sent Events (SSE) endpoint that streams AI responses.

public @interface AI {
String sse(); // SSE endpoint for AI assistant streaming
}
AttributeTypeDescription
sseStringPath to the SSE endpoint that provides AI responses
@UI("/support")
@AI(sse = "/api/ai/stream")
public class SupportPage { ... }

@UI("/home")
@Title("My first Mateu app")
@Style(StyleConstants.CONTAINER)
public class Home {
@NotEmpty
String name;
@Button
public Message greet() {
return new Message("Hello " + name);
}
}

A full application shell combining several annotations:

@UI("/_workflow")
@FavIcon("/images/favicon.svg")
@PageTitle("Workflow Engine")
@Logo("/images/logo.svg")
@Title("Workflow Engine")
public class WorkflowHome {
@Menu
WorkflowMenu workflow;
}