Multi-page apps

A multi-page app builds several pages from one project. Each page is a separate bundle and its own Angular app, with its own bootstrapApplication(), root component and services. Use pages when a native app shows independent Lynx screens, such as a main app plus a separate settings screen.

How people move between pages

Angular Router can't open another page, because each page is a separate app. The host app (the native iOS or Android app that runs your bundles) opens each page in its own view.

  • The app that ng build --platform ios or --platform android generates shows only main.lynx.bundle. It copies your other bundles into the app but never opens them.
  • To open the others, eject the generated project and add the native code yourself (see Run on iOS and Android), or embed the bundles in your own native app.

For screens inside one app, use routing instead.

Add a page in lynx.config.ts

List each page under source.entry. The key is the page name, and the value is its entry file:

lynx.config.ts
import { defineConfig } from '@blotch/angular-lynx-build';

export default defineConfig({
  source: {
    entry: {
      main: './src/main.ts',
      settings: './src/pages/settings/main.ts',
    },
  },
});

Give each page an entry file that bootstraps its own root component:

src/pages/settings/main.ts
import { bootstrapApplication } from '@blotch/angular-lynx';
import { Settings } from './settings';
import { settingsConfig } from './settings.config';

bootstrapApplication(Settings, settingsConfig);
src/pages/settings/settings.config.ts
import {
  type ApplicationConfig,
  provideZonelessChangeDetection,
} from '@angular/core';
import { provideRenderer } from '@blotch/angular-lynx';

export const settingsConfig: ApplicationConfig = {
  providers: [provideZonelessChangeDetection(), provideRenderer()],
};
  • One bundle per key. ng build writes main.lynx.bundle and settings.lynx.bundle, plus a .web.bundle of each for the web preview.
  • source.entry replaces the single entry that ng build otherwise takes from browser in angular.json.
  • Keep a page called main. The generated native app opens main.lynx.bundle, and ng build --platform stops with an error without it.
  • Each page has its own providers. Give it its own ApplicationConfig, with routes if it needs them.

Or define each page as an angular.json project

If you'd rather see each page as a project in your workspace, add one application project per page:

angular.json
{
  "projects": {
    "main": {
      "projectType": "application",
      "root": ".",
      "sourceRoot": "src",
      "architect": {
        "build": {
          "builder": "@blotch/angular-lynx-build:application",
          "options": {
            "browser": "src/main.ts",
            "tsConfig": "tsconfig.app.json"
          }
        },
        "serve": {
          "builder": "@blotch/angular-lynx-build:dev-server",
          "options": { "buildTarget": "main:build" }
        }
      }
    },
    "settings": {
      "projectType": "application",
      "root": ".",
      "sourceRoot": "src",
      "architect": {
        "build": {
          "builder": "@blotch/angular-lynx-build:application",
          "options": {
            "browser": "src/pages/settings/main.ts",
            "tsConfig": "tsconfig.app.json"
          }
        }
      }
    }
  }
}

Then turn on the pages option in lynx.config.ts:

lynx.config.ts
import { defineConfig, pluginAngularLynx } from '@blotch/angular-lynx-build';

export default defineConfig({
  plugins: [
    pluginAngularLynx({
      pages: 'all', // every application project, or e.g. ['main', 'settings']
    }),
  ],
});
  • Project names become bundle names. Name the first project main, for the same reason as above.
  • Name a project when you run the CLI. Both projects share the workspace root, so run ng build main or ng serve main. Either one builds every page.
  • All pages must share one tsConfig. The build compiles them in a single pass and stops if they differ.
  • pages replaces source.entry, so use one setup or the other.

Open each page while you develop

ng serve prints a Lynx URL and a Web URL, with a ∟ Preview link, for every page. Each one loads only that page.

  • In Lynx Explorer, the QR code is for the first page. To show another page's QR code, press r in the terminal and pick the page. You can also paste a page's Lynx URL into "Enter Card URL".
  • In the web preview, open the page's ∟ Preview link. Its URL names the page's web bundle, such as settings.web.bundle.

Share data between pages

Pages don't share services, signals or router state, because each is a separate app. To pass values between them while the app runs, use LynxSessionStorage.

Limitations

  • The generated native app opens only main. See the note at the top of this page.
  • Each bundle carries its own copy of Angular. Two small pages are each about as big as a one-page app.
  • One tsConfig for every page.