Hilla Documentation

Application Basics

An introduction to reactive UIs using Hilla.

A Hilla application is written in TypeScript and runs in a single HTML page. An application consists of one or more views, each bound to a route or a URL path. To access business data and logic, an application can have server-side endpoints written in Java.

An Introduction to Reactive UIs

Views in Hilla applications are programmed in a reactive, rather than an imperative, manner, as you would with Vaadin Flow, jQuery, and so forth. Reactive views have fewer moving parts and, because of this, they are easier to understand and debug. In reactive UI programming, the application UI is the value of a function. The function gets the component’s state as a parameter and returns HTML. Whenever the state changes, the UI is re-rendered.

Open in a
new tab

In reactive programming, there is only one state: the data. The UI always reflects that state. You define a template using values from the state. Whenever the model changes, the template is automatically updated.

export class ReactiveView extends LitElement {
  // The data
  @property({ type: Number })
  count = 0;

  // Called whenever the data changes
  render() {
    return html` <div>
      <div>The button has been clicked ${this.count} times</div>
      <vaadin-button @click="${this.increment}">Click me!</vaadin-button>

  // Change the data
  private increment() {

Application Architecture

Most of the application logic is handled in application views. You could have a login view, registration view, main view, and various other views. To have a typical main view with menu navigation and multiple sub-views, you can use the App Layout component.

The entry point of a Hilla application is the application shell, which consists of the following files:


A bootstrap page that loads the application. You do not normally need to modify the file.


The TypeScript entry point of the application. This is where you set up routing and other application tasks. To navigate between views, you need to define routes. See Defining Routes for more details.

Most of an application consists of views, as described next.

Adding a View

Views in Hilla are custom HTML elements that extend LitElement, View, or Layout, which handle rendering the component state reactively. You minimally need to implement a render() function that returns the rendered HTML representation of the component. You can also provide custom styling by implementing a styles() function that returns custom CSS. See LitElement Basics for a more thorough introduction to using LitElement.

The following is an example of a view in Hilla:

Open in a
new tab
export class MyView extends LitElement {
  render() {
    return html`<vaadin-button @click="${this.sayHello}">Say hello</vaadin-button>`;

  private sayHello() {

Basic Routing

In order to see the new client-side view in the browser, you need to define a new client-side route for it. A route is a path in the URL. This requires the following changes in the routes.ts file:

import { Router } from '@vaadin/router';
import './my-view'; 1

export const routes = [
    // other views
    { path: 'my-view-path', component: 'my-view' }, 2
  1. Import the view.

  2. Define the route mapping.

Now my-view is accessible at the my-view-path path, that is, http://localhost:8080/my-view-path. All the other routes are handled by the server-side router. See Defining Routes for more information.

Accessing Backend Data

Hilla provides a type-safe and secure way to access data from the backend in frontend views by using generated TypeScript code. Hilla scans the backend code during development and generates TypeScript code that can be used to call the corresponding Java methods. The generated code is processed in the same way as other TypeScript views. Only the necessary code is included in the production application bundle.

See Accessing Java Backend for more information.