App configuration and startup

Configure Aurelia applications, register global resources, and choose the startup pattern that fits your project.

Application Startup

Aurelia provides two main approaches for application startup: a quick setup using static methods with sensible defaults, and a verbose setup that gives you complete control over configuration.

Before you start: If you have not already chosen a project scaffold, walk through the section overview for context on how this guide fits with enhancement, routing, and composition topics.

Quick startup

The quick startup approach uses static methods on the Aurelia class and is the most common choice for new applications.

import Aurelia from 'aurelia';
import { RouterConfiguration } from '@aurelia/router';

import { MyRootComponent } from './my-root-component';

// Simplest startup - hosts to <my-root-component> element, or <body> if not found
Aurelia.app(MyRootComponent).start();

// Register additional features before startup
Aurelia
  .register(
    RouterConfiguration.customize({ useUrlFragmentHash: false })
  )
  .app(MyRootComponent)
  .start();

// Specify a custom host element
Aurelia
  .register(
    RouterConfiguration.customize({ useUrlFragmentHash: false })
  )
  .app({
    component: MyRootComponent,
    host: document.querySelector('my-start-tag')
  })
  .start();

// Async startup pattern (recommended)
const app = Aurelia
  .register(
    RouterConfiguration.customize({ useUrlFragmentHash: false })
  )
  .app(MyRootComponent);

await app.start();

Verbose Startup

The verbose approach gives you complete control over the DI container and configuration. Use this when integrating Aurelia into existing applications or when you need fine-grained control.

import { Aurelia, StandardConfiguration } from '@aurelia/runtime-html';
import { RouterConfiguration } from '@aurelia/router';
import { LoggerConfiguration, LogLevel } from '@aurelia/kernel';
import { ShellComponent } from './shell';

// Create Aurelia instance with explicit configuration
const au = new Aurelia();

au.register(
  StandardConfiguration,  // Essential runtime configuration
  RouterConfiguration.customize({ useUrlFragmentHash: false }),
  LoggerConfiguration.create({ level: LogLevel.debug })
);

au.app({
  host: document.querySelector('body'),
  component: ShellComponent
});

// Always await start() for proper error handling
await au.start();

When to use verbose startup:

  • Integrating Aurelia into existing applications

  • Custom DI container configuration needed

  • Multiple Aurelia apps in one page

  • Advanced debugging or testing scenarios

StandardConfiguration includes essential services like:

  • Template compiler and renderer

  • Binding engine and observers

  • Custom element/attribute support

  • Built-in value converters and binding behaviors

  • DOM event handling and delegation

  • Shadow DOM and CSS module support

Registering Global Resources

Registering a single custom element

To make a custom element globally available throughout your application, register it before calling app().

import Aurelia from 'aurelia';
import { CardCustomElement } from './components/card';

// Quick startup
Aurelia
  .register(CardCustomElement)  // No type casting needed
  .app(MyRootComponent)
  .start();

// Verbose startup
const au = new Aurelia();
au.register(
  StandardConfiguration,
  CardCustomElement
);
au.app({ host: document.body, component: MyRootComponent });
await au.start();

Registering multiple resources

Group related components into resource modules for better organization.

src/components/index.ts:

export { CardCustomElement } from './card';
export { CollapseCustomElement } from './collapse';
export { ModalCustomElement } from './modal';

src/main.ts:

import Aurelia from 'aurelia';
import * as GlobalComponents from './components';

// Register all exported components at once
Aurelia
  .register(GlobalComponents)
  .app(MyRootComponent)
  .start();

Registering other resource types

import Aurelia from 'aurelia';
import { MyValueConverter } from './converters/my-value-converter';
import { MyBindingBehavior } from './behaviors/my-binding-behavior';
import { MyCustomAttribute } from './attributes/my-custom-attribute';

Aurelia
  .register(
    MyValueConverter,
    MyBindingBehavior,
    MyCustomAttribute
  )
  .app(MyRootComponent)
  .start();

Advanced Configuration

Custom DI registrations

import { Registration } from '@aurelia/kernel';
import { MyService, IMyService } from './services/my-service';

Aurelia
  .register(
    Registration.singleton(IMyService, MyService)
  )
  .app(MyRootComponent)
  .start();

Environment-specific configuration

import Aurelia, { LoggerConfiguration, LogLevel } from 'aurelia';

const isProduction = process.env.NODE_ENV === 'production';

Aurelia
  .register(
    LoggerConfiguration.create({
      level: isProduction ? LogLevel.warn : LogLevel.debug
    })
  )
  .app(MyRootComponent)
  .start();

Enhancement Mode

Sometimes you need Aurelia to light up markup that already exists in the DOM. Instead of calling app(), reach for Aurelia.enhance:

const enhanceRoot = await Aurelia.enhance({
  host: document.querySelector('#existing-content'),
  component: { message: 'Hello from enhanced content!' }
});

Enhancement is ideal for progressive hydration, CMS integrations, or widgets embedded in non-Aurelia pages. You can register resources before enhancing, provide a custom DI container, and tear down the enhanced view by calling enhanceRoot.deactivate() when you’re done.

For a full guide, including cleanup patterns, lifecycle hooks, and advanced recipes, see the dedicated Enhance article.

Next steps

Last updated

Was this helpful?