Skip to main content
Jet is built on Angular’s latest features, leveraging standalone components, signals, and functional patterns to create a modern, maintainable application architecture.

Application Configuration

The application is bootstrapped through app.config.ts, which configures all providers and application-wide settings:
export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(withFetch(), withInterceptors([progressBarInterceptor])),
    { provide: LOCALE_ID, useValue: window.navigator.language },
    provideBrowserGlobalErrorListeners(),
    provideEnvironmentInitializer(() => {
      inject(ServiceWorkerService);
    }),
    { provide: MatPaginatorIntl, useClass: JetMatPaginatorIntl },
    {
      provide: MAT_SNACK_BAR_DEFAULT_OPTIONS,
      useValue: { duration: 5000, verticalPosition: 'top' },
    },
    provideRouter(
      routes,
      withComponentInputBinding(),
      ...(isDevMode() ? [withDebugTracing()] : []),
      withInMemoryScrolling({ anchorScrolling: 'enabled', scrollPositionRestoration: 'enabled' }),
    ),
    provideServiceWorker('ngsw-worker.js', {
      enabled: !isDevMode(),
      registrationStrategy: 'registerWhenStable:30000',
    }),
    provideTransloco({
      config: {
        availableLangs: LANGUAGE_OPTIONS.map(
          (languageOption: LanguageOption): Language => languageOption.value,
        ),
        defaultLang: DEFAULT_LANGUAGE_OPTION.value,
        prodMode: !isDevMode(),
        reRenderOnLangChange: true,
      },
      loader: TranslocoHttpLoader,
    }),
  ],
};

Key Architectural Features

Standalone Components

All components in Jet use Angular’s standalone API, eliminating the need for NgModules:
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [TranslocoModule, PageComponent],
  selector: 'jet-home-page',
  styleUrl: './home-page.component.scss',
  templateUrl: './home-page.component.html',
})
export class HomePageComponent {
  readonly #loggerService = inject(LoggerService);

  public constructor() {
    this.#loggerService.logComponentInitialization('HomePageComponent');
  }
}

Signal-Based State Management

Jet uses Angular signals for reactive state management:
public constructor() {
  this.#user = signal(null);

  this.#supabaseClient.auth.onAuthStateChange(
    (_authChangeEvent: AuthChangeEvent, authSession: AuthSession | null): void => {
      this.#user.set(authSession?.user ?? null);
    },
  );
}

public get user(): Signal<null | User> {
  return this.#user.asReadonly();
}

Effects for Side Effects

Signal effects handle reactive side effects with proper tracking:
effect(
  () => {
    this.#loggerService.logEffectRun('colorSchemeOption');

    const colorSchemeOption: ColorSchemeOption = this.#colorSchemeOption();

    untracked(() => {
      this.#setColorScheme(colorSchemeOption.value);
      this.#setThemeColorMeta(colorSchemeOption.value);
    });
  },
  { debugName: 'colorSchemeOption' },
);

Computed Signals

Derived state is created using computed signals:
this.directionality = computed(() => this.#settings().languageOption.directionality);
this.matSidenavMode = computed(() => (this.isLargeViewport() ? 'side' : 'over'));
this.shouldAddSafeArea = computed(() =>
  this.matSidenavMode() === 'over' ? true : !this.isMatSidenavOpen(),
);

HTTP Interceptors

Jet uses functional HTTP interceptors for cross-cutting concerns:
export const progressBarInterceptor: HttpInterceptorFn = (req, next) => {
  const progressBarService = inject(ProgressBarService);

  const method = req.method;

  if (['GET', 'HEAD', 'OPTIONS'].includes(method)) {
    progressBarService.showQueryProgressBar();
  } else if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) {
    progressBarService.showIndeterminateProgressBar();
  }

  return next(req).pipe(
    finalize(() => {
      progressBarService.hideProgressBar();
    }),
  );
};

Progressive Web App (PWA)

Jet includes built-in PWA support with service worker configuration:
  • Service worker registration strategy: registerWhenStable:30000
  • Only enabled in production mode
  • Automatic update management through ServiceWorkerService

Internationalization (i18n)

The application uses Transloco for internationalization:
  • Multiple language support configured via LANGUAGE_OPTIONS
  • RTL support through directionality settings
  • Dynamic language switching with re-render support
  • Custom loader for translation files

Change Detection Strategy

All components use OnPush change detection for optimal performance:
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  // ...
})
This strategy, combined with signals, ensures efficient reactivity throughout the application.

Environment Initialization

Critical services are initialized at application startup:
provideEnvironmentInitializer(() => {
  inject(ServiceWorkerService);
})
This ensures services like ServiceWorkerService are instantiated immediately when the application starts.
Jet’s architecture prioritizes modern Angular patterns, type safety, and performance optimization through signals and OnPush change detection.

Build docs developers (and LLMs) love