Modifying the Bootstrap Page at the Runtime

Application Shell

The App Shell Model tries to make your website faster by loading the 'important' parts of the web page at first causing a good first impression. The key for this, is to deliver the minimal HTML, CSS and JavaScript required to display the user interface during the first visit, and eventually cache it to be used in future revisits.

The Application Shell in Vaadin is also known as Bootstrap Page or simply index.html.

Modifying the Application Shell

In Vaadin 15+ the user has full control on the index.html contents, which can by modified in different ways:

  1. In client-side by editing the frontend/index.html when the content is static, for instance the <viewport> tag.

  2. In server-side for changes that require some dynamic server content or just when Java syntax is preferred, for example making the application installable by enabling the @PWA built-in feature.

    • Implement the AppShellConfigurator for cases covered by the AppShellSettings API, or by annotations.

    • Configure an IndexHtmlRequestListener for advanced cases modifying the document structure.

Customizing the Application Shell Template

By default, during the first request, Vaadin parses the frontend/index.html template file and delivers it with a few modifications as described in the Default Bootstrap Template

This is the best place for customizing the app-shell, for example to put an analytics tag in the page.

  <title>My App</title>
  <!-- Google Analytics -->
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),

    ga('create', 'UA-XXXXX-Y', 'auto');
    ga('send', 'my-app-bootstrap');

Customizing the Application Shell during Runtime

The AppShellConfigurator Interface

In Java code, use the AppShellConfigurator marker interface rather than editing the index.html when adding dynamic content during the bootstrap process.

There must be a single application shell for the entire Vaadin application, and therefore there can be at max one class implementing AppShellConfigurator.
AppShellConfigurator is a replacement of the obsolete PageConfigurator interface.

The AppShellConfigurator#configurePage Method

Override configurePage for adding content to the index.html template by calling the following AppShellSettings methods:

  • AppShellSettings#setViewport to set the viewport value, it replaces the viewport present in the index.html template.

  • AppShellSettings#setPageTitle to set the initial page title, replaces the template title tag.

  • AppShellSettings#setBodySize to configure the body width and height values.

  • AppShellSettings#addMetaTag to append meta tags to the head.

  • AppShellSettings#addInlineFromFile to include content from resource files.

  • AppShellSettings#addInlineWithContents to add arbitrary content.

  • AppShellSettings#addLink to add links to the head.

  • AppShellSettings#addFavIcon to configure the favicon.

  • AppShellSettings#getLoadingIndicatorConfiguration for configuring loading indicator when legacy bootstrapping is used (deprecated, see details after code example).

  • AppShellSettings#getReconnectDialogConfiguration for configuring the reconnect dialog when legacy bootstrapping is used (deprecated, see details after code example).

  • AppShellSettings#getPushConfiguration to customize the push mechanism when legacy bootstrapping is used (deprecated, see details after code example).

public class AppShell implements AppShellConfigurator {

  public void configurePage(AppShellSettings settings) {
    settings.setViewport("width=device-width, initial-scale=1");
    settings.setPageTitle("A cool vaadin app");
    settings.setBodySize("100vw", "100vh");
    settings.addMetaTag("author", "bunny");
    settings.addFavIcon("icon", "icons/icon-192.png", "192x192");
    settings.addLink("shortcut icon", "icons/favicon.ico");

            "console.log(\"foo\");", Wrapping.JAVASCRIPT);
public class ServiceListener implements VaadinServiceInitListener{

    public void serviceInit(ServiceInitEvent event) {
        event.getSource().addUIInitListener(uiInitEvent -> {
            LoadingIndicatorConfiguration indicator = uiInitEvent.getUI().getLoadingIndicatorConfiguration();

            PushConfiguration push = uiInitEvent.getUI().getPushConfiguration();
            ReconnectDialogConfiguration dialog = uiInitEvent.getUI().getReconnectDialogConfiguration();

Java Annotations

Vaadin provide a set annotations for modifying the application shell, though, unlike in previous versions, in Vaadin 15 these annotations must be placed in the application shell class.

  • @Viewport to set the viewport value.

  • @PageTitle to set the initial page title.

  • @BodySize to configure the body size.

  • @Meta to append meta tags to the head.

  • @Inline to include content from resource files in the index.html.

  • @PWA to define application PWA properties.

  • @Push to configures server push.

@Viewport("width=device-width, initial-scale=1")
@PageTitle("A cool vaadin app")
@BodySize(height = "100vh", width = "100vw")
@Meta(name = "author", content = "bunny")
@Inline(wrapping = Wrapping.AUTOMATIC,
        position = Position.APPEND,
        target = TargetElement.BODY,
        value = "custom.html")
@PWA(name = "Cool Vaadin App", shortName = "my-app")
@Push(value = PushMode.MANUAL, transport = Transport.WEBSOCKET)
public class AppShell implements AppShellConfigurator {
Modifications in the AppShellConfigurator#configurePage do have priority over the equivalent annotations.
Annotations do not cover all the cases that can be done when overriding the AppShellConfigurator#configurePage method

The IndexHtmlRequestListener Interface

In addition, for advance cases not covered in the previous section, the content can be modified via an IndexHtmlRequestListener.

An implementation of the listener should be added via a ServiceInitEvent when a VaadinService is initialized. Check the ServiceInitListener tutorial for the details about using Vaadin ServiceInitListeners.

The example below changes the body class dynamically:

public class MyIndexHtmlRequestListener implements
        IndexHtmlRequestListener {

    public void modifyIndexHtmlResponse(
            IndexHtmlResponse indexHtmlResponse) {

        Document document = indexHtmlResponse.getDocument();
        Element body = document.body();

    private Set<String> computeBodyClassNames() {
        // Introduce some logic to dynamically change the body class
        return Collections.singleton("my-className");

It can also be provided as a servlet container deployment property with the name useDeprecatedV14Bootstrapping.