Docs

Application architecture

An overview of the structure and architecture of a Hilla application.

Hilla applications are written in TypeScript and they run on a single HTML page. An application consists of one or more views, each bound to a route (i.e. URL path). To access business data and logic, an application can have server-side endpoints written in Java.

Project structure

The following files are important parts of a Hilla project:

frontend/index.html

A bootstrap page that loads the application. You don’t normally need to modify this file.

frontend/index.ts

The TypeScript entry point of the application. You don’t normally need to modify this file.

frontend/views/

Most of your application consists of views. It’s not required, but you should place your view implementations in this folder.

frontend/routes.ts

This is where you set up routing and other application tasks.

frontend/themes/<app-name>/styles.css

The main style sheet for your application theme, where you can add your custom CSS.

src/main/java/

You define your server-side endpoints here, using Java packages and classes. Endpoints allow your client-side views access to the back-end data.

Application views

Most of the application logic is handled in application views. You could have a login view, registration view, main view, and various other views.

Views in a Hilla application 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 Creating components for a more thorough introduction to using LitElement.

The following is an example of a view in Hilla:

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

  private sayHello() {
    Notification.show('Hello');
  }
}

To have a typical main view with menu navigation and multiple sub-views, you can use the App Layout component.

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.

@customElement('reactive-view')
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>
      </div>
    `;
  }

  // Change the data
  private increment() {
    this.count++;
  }
}

Routing

To see a view in the browser, and to navigate between the views, you need to define client-side routes for them. 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. See Routing and navigation for more details.

Accessing back-end data

Hilla provides a type-safe and secure way to access data from the backend in front-end views by using generated TypeScript code. Hilla scans the back-end 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 Endpoints for more information.