The SeedStack W20 bridge acts as an integration bridge between the Seed Java framework and the W20 Web framework.

You can add it with the following dependency:

Show version
dependencies {

If you don’t want to serve W20 static files from the Java application, use the following dependency instead:

Show version
dependencies {

This will only provide the REST API required by the W20 frontend to bridge. Use the default masterpage template presented below to update your own index.html page on the frontend.

How it works

The W20 bridge automatically generates and serves W20 resources that should normally be written manually:

  • The W20 masterpage is automatically generated and served under /. There is no need to provide an index.html file, except for advanced use cases (see below).
  • The W20 configuration file ( is read from the META-INF/configuration classpath location and a managed, enriched version is served under /seed-w20/application/configuration.
  • A resource for basic authentication is served under /seed-w20/security/basic-authentication,
  • A resource for retrieving the authorizations of the authenticated subject is served under /seed-w20/security/authorizations.

Automatic activation of fragments

The W20 bridge automatically detects W20 fragments (manifests ending with the .w20.json extension) present in the classpath under META-INF/resources and enables them in the generated W20 configuration.

Note that the W20 bridge cannot detect fragments located outside the local classpath, like the ones in the document root or external to the application. Those fragments must still be explicitly specified in the W20 configuration.

Fragment variables

The W20 bridge provides several fragments variables containing path information about the application. These variables can be used as ${variable-name[:default-value]} placeholders in the fragment manifests:

  • seed-base-path: the application base path without a trailing slash,
  • seed-base-path-slash: the application base path with a trailing slash,
  • seed-rest-path: the path under which the REST resources are served (without a trailing slash),
  • seed-rest-path-slash: the path under which the REST resources are served (with a trailing slash),
  • components-path: the path under which the Web components are served (without a trailing slash),
  • components-path-slash: the path under which the Web components are served (with a trailing slash).

Automatic configuration

Several aspects of the configuration are automatically managed:

  • The application identifier (w20-core -> application -> id) is automatically set with the same value as the backend application identifier,
  • The environment type (w20-core -> env -> type) is automatically set to the org.seedstack.w20.environment property if any.
  • Several elements in the masterpage are automatically derived from the bridge configuration values. See the configuration section below for more details.

The FragmentConfigurationHandler interface can be implemented to further enrich or override the generated configuration. As an example, it is used by the i18n add-on for automatically managing the frontend culture module if backend internationalization is active.


The behavior of W20 bridge can be altered with several backend configuration properties, described below:

  # If true, AngularJS HTML5 mode and the redirect filter is enabled (defaults to true)
  prettyUrls: (boolean)
  # If true, no master page is generated by the bridge and a custom one must be provided (defaults to false)
  disableMasterpage: (boolean)
  # The classpath location of the masterpage template (defaults to org/seedstack/w20/masterpage.html) 
  masterpageTemplate: (String)
  # The W20 loading timeout (defaults to 30)
  loadingTimeout: (int)
  # If true, CORS request will be made with credentials (allows to access secured resource on other domains)
  corsWithCredentials: (boolean)
  # The path of the bower components directory, relative to the context root
  componentsPath: (String)
  # The security provided for seed-w20 fragment (defaults to BasicAuthentication)
  securityProvider: (String)
  # Information about the application
    # The W20 application title (defaults to the SeedStack application name)
    title: (String)
    # The W20 application subtitle (no default)
    subTitle: (String)
    # The W20 application version (defaults to the SeedStack version)
    version: (String)
    # The environment (development, pre-production, production, ...)
    environment: (String)

To dump the w20 configuration options:

mvn -q -Dargs="w20" seedstack:config

Pretty URLs

By default AngularJS HTML5 mode is enabled when using the W20 bridge. Its allows pretty URLs to be used instead of historic hashbang URLs (#!). To achieve this, a servlet filter is automatically placed at the root of the application: it redirects any URL that doesn’t exist on the server to the masterpage, so the W20 frontend can load and AngularJS can then display the corresponding view.

The HTML5 redirect filter tries its best to avoid redirecting legitimate 404 or special cases like WebSocket upgrades. To ensure that your REST API calls returning legitimate 404 are not redirected by the filter, you must place the API on its own base path (like /api). See the REST manual page to learn how to do so.

Custom masterpage

Each theme provides its own general-purpose masterpage template. If no theme is used or the theme doesn’t contain a masterpage, the W20 bridge will fallback to a default masterpage with minimal body content.

Masterpage templates can use ${} placeholders for some configuration-dependant values. The following variables are available:

  • applicationTitle,
  • applicationSubtitle,
  • applicationVersion,
  • timeout,
  • corsWithCredentials,
  • basePath,
  • basePathSlash,
  • restPath,
  • restPathSlash,
  • componentsPath,,
  • componentsPathSlash.

Below, you can find the fallback masterpage template that can be used as a starting point for your own custom templates:

<!doctype html>
<html data-w20-app="${restPathSlash}seed-w20/application/configuration" data-w20-app-version="${applicationVersion}" data-w20-timeout="${timeout}" data-w20-cors-with-credentials="${corsWithCredentials}">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta charset="utf-8">
    <script type="text/javascript" data-main="${componentsPathSlash}w20/modules/w20.js?__v=${applicationVersion}" src="${componentsPathSlash}requirejs/require.js?__v=${applicationVersion}"></script>
    <base href="${basePathSlash}">
<div id="w20-loading-cloak">
    <div class="w20-loading-indicator"></div>
<div id="w20-view" class="w20-content" data-ng-view></div>
<div data-w20-error-report></div>