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.