Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Scalable Angular Architectures with Route-Based...

Scalable Angular Architectures with Route-Based Architecture

Architecture decisions in Angular often start with the routes. In this talk, Fabian Gosebrink shows how clean modules, libraries, and state areas can be derived from routing structures. With Nx, he supports modularization and keeps dependencies under control. The result: an architecture that grows with its requirements and gives teams clear orientation. Attendees learn how to structure complex applications along their routes and keep them maintainable over the long term.

Avatar for Fabian Gosebrink

Fabian Gosebrink

October 02, 2026

More Decks by Fabian Gosebrink

Other Decks in Technology

Transcript

  1. 1 app/ 2 products.component.ts 3 product.component.ts 4 checkout.component.ts 5 header.component.ts

    6 products.service.ts 7 checkout.service.ts 8 product.model.ts 9 10 product-detail.component.ts 11 product-image.component.ts 12 product-info.component.ts 13 product-detail.service.ts 14 cart.model.ts ... 15
  2. 1 app/ 2 products.component.ts 3 product.component.ts 4 checkout.component.ts 5 header.component.ts

    6 products.service.ts 7 checkout.service.ts 8 product.model.ts 9 product-detail.component.ts 10 product-image.component.ts 11 product-info.component.ts 12 product-detail.service.ts 13 cart.model.ts 14 15 ...
  3. 1 app/ 2 components/ products/ 3 product-detail/ 4 checkout/ 5

    header/ 6 7 services/ 8 products.service.ts 9 product-detail.service.ts 10 checkout.service.ts 11 12 models/ 13 14 product.model.ts 15 cart.model.ts
  4. 1 app/ 2 components/ products/ 3 product-detail/ 4 checkout/ 5

    header/ 6 7 services/ 8 products.service.ts 9 product-detail.service.ts 10 checkout.service.ts 11 12 models/ 13 product.model.ts 14 cart.model.ts 15
  5. 1 app/ 2 components/ products/ 3 product-detail/ 4 5 checkout/

    6 header/ 7 8 services/ 9 products.service.ts 10 product-detail.service.ts 11 checkout.service.ts 12 13 models/ 14 product.model.ts 15 cart.model.ts
  6. 1 app/ 2 components/ 3 products/ product-detail/ 4 5 checkout/

    6 header/ 7 8 services/ 9 products.service.ts product-detail.service.ts 10 11 checkout.service.ts 12 13 models/ 14 product.model.ts 15 cart.model.ts
  7. 1 app/ 2 components/ 3 products/ product-detail/ 4 5 checkout/

    6 header/ 7 8 services/ 9 products.service.ts product-detail.service.ts 10 11 checkout.service.ts 12 13 models/ product.model.ts 14 15 cart.model.ts
  8. 1 2 export const routes: Routes = [ { path:

    'products', ... }, 3 { path: 'products/:id', ... }, 4 { path: 'checkout', ... }, 5 6 ];
  9. 1 features/ 2 products/ 3 container/ 4 products/ 5 presentational/

    6 product/ 7 product-category/ 8 service/ 9 products.service.ts
  10. 1 product-detail/ 2 container/ 3 product-detail/ 4 presentational/ 5 add-to-cart-button/

    6 product-image/ 7 product-info/ 8 service/ 9 product-detail.service.ts
  11. products/ → product listing → service product-detail/ → detail page

    → image → product info → add-to-cart → service
  12. 1 2 3 4 5 6 7 8 9 10

    11 12 13 14 15 { path: 'products', loadComponent: () => import('...').then((c) => c.ProductsComponent), }, { path: 'products/:id', loadComponent: () => import('...').then((c) => c.ProductDetailComponent), }, { path: 'checkout', loadComponent: () => import('...').then((c) => c.CheckoutComponent), }
  13. 1 { path: 'checkout', 2 providers: [ 3 4 provideState({

    name: featureKey, reducer: featureReducer }), 5 provideEffects(FeatureEffects), ], 6 children: [...] 7 8 }
  14. 1 { 2 products: { 3 ... }, 4 product-detail:

    { 5 6 ... 7 }, 8 checkout: { 9 ... 10 } 11 }
  15. 1 // features/checkout/checkout.routes.ts 2 3 export const checkoutRoutes: Routes =

    [ 4 { path: '', component: CheckoutComponent }, 5 { path: 'address', component: AddressComponent }, 6 { path: 'payment', component: PaymentComponent }, 7 { path: 'summary', component: SummaryComponent }, 8 ];
  16. 1 // features/checkout/checkout.routes.ts 2 3 export const checkoutRoutes: Routes =

    [ 4 { path: '', component: CheckoutComponent }, 5 { path: 'address', component: AddressComponent }, 6 { path: 'payment', component: PaymentComponent }, 7 { path: 'summary', component: SummaryComponent }, 8 ];
  17. 1 // features/checkout/checkout.routes.ts 2 3 export const checkoutRoutes: Routes =

    [ 4 { path: '', component: CheckoutComponent }, 5 { path: 'address', component: AddressComponent }, 6 { path: 'payment', component: PaymentComponent }, 7 { path: 'summary', component: SummaryComponent }, 8 ];
  18. 1 // app.routes.ts 2 3 { 4 path: 'checkout', 5

    loadChildren: () => 6 import('./features/checkout').then((m) => m.checkoutRoutes), 7 }
  19. 1 // app.routes.ts 2 3 { 4 path: 'checkout', 5

    loadChildren: () => 6 import('./features/checkout').then((m) => m.checkoutRoutes), 7 }
  20. 1 features/ 2 checkout/ 3 checkout.routes.ts 4 container/ 5 checkout/

    6 address/ 7 payment/ 8 payment-method/ 9 credit-card/ 10 paypal/ summary/ 11 12 confirmation/ 13 presentational/ 14 ... 23 folders
  21. 1 features/ 2 checkout/ 3 checkout.routes.ts 4 container/ 5 checkout/

    6 address/ 7 payment/ 8 payment-method/ 9 credit-card/ 10 paypal/ 11 summary/ 12 confirmation/ 13 presentational/ 14 ... 23 folders
  22. 1 features/ 2 checkout/ 3 checkout.routes.ts 4 container/ 5 checkout/

    6 address/ 7 payment/ 8 payment-method/ 9 credit-card/ 10 paypal/ summary/ 11 12 confirmation/ 13 presentational/ 14 ... 23 folders
  23. 1 features/ 2 checkout/ 3 checkout.routes.ts 4 container/ 5 checkout/

    6 address/ 7 payment/ 8 payment-method/ 9 credit-card/ 10 paypal/ 11 summary/ 12 confirmation/ 13 presentational/ 14 ... 23 folders
  24. 1 features/ 2 checkout/ 3 checkout.routes.ts 4 main/ 5 container/

    6 presentational/ 7 ... 8 payment/ 9 payment.routes.ts container/ 10 presentational/ 11 12 ...
  25. 1 features/ 2 checkout/ 3 checkout.routes.ts 4 main/ 5 container/

    6 presentational/ 7 ... 8 payment/ 9 payment.routes.ts 10 container/ 11 presentational/ 12 ...
  26. 1 features/ 2 checkout/ 3 checkout.routes.ts 4 main/ 5 container/

    6 presentational/ 7 ... 8 payment/ 9 payment.routes.ts container/ 10 presentational/ 11 12 ...
  27. 1 features/ 2 checkout/ 3 checkout.routes.ts 4 main/ 5 container/

    6 presentational/ 7 ... 8 payment/ 9 payment.routes.ts 10 container/ 11 presentational/ 12 ...
  28. 1 2 3 4 5 6 7 @Component({ selector: 'app-header',

    templateUrl: './header.component.html', }) export class HeaderComponent { cartProductsCount = input.required<number>(); }
  29. 1 2 3 4 5 6 7 @Component({ selector: 'app-header',

    templateUrl: './header.component.html', }) export class HeaderComponent { cartProductsCount = input.required<number>(); }
  30. 1 2 3 4 5 6 7 <!-- features/shell/container/shell/shell.component.html -->

    <app-header [cartProductsCount]="store.cartProductsCount()" /> <div class="content"> <router-outlet /> </div>
  31. 1 2 3 4 5 6 7 <!-- features/shell/container/shell/shell.component.html -->

    <app-header [cartProductsCount]="store.cartProductsCount()" /> <div class="content"> <router-outlet /> </div>
  32. 1 2 3 4 5 6 7 <!-- features/shell/container/shell/shell.component.html -->

    <app-header [cartProductsCount]="store.cartProductsCount()" /> <div class="content"> <router-outlet /> </div>
  33. 1 features/ 2 products/ 3 cart.service.ts container/ 4 5 presentational/

    6 7 product-detail/ cart.service.ts 8 9 container/ 10 presentational/ 11 12 checkout/ 13 cart.service.ts container/ 14 15 presentational/ ? ? ?
  34. 1 features/ 2 products/ 3 cart.service.ts 4 container/ 5 presentational/

    6 7 product-detail/ 8 cart.service.ts 9 container/ 10 presentational/ 11 12 checkout/ 13 cart.service.ts 14 container/ 15 presentational/ ? ? ?
  35. 1 features/ 2 products/ 3 cart.service.ts 4 container/ 5 presentational/

    6 7 product-detail/ cart.service.ts 8 9 container/ 10 presentational/ 11 12 checkout/ 13 cart.service.ts 14 container/ 15 presentational/ ? ? ?
  36. 1 features/ 2 products/ 3 cart.service.ts 4 container/ 5 presentational/

    6 7 product-detail/ cart.service.ts 8 9 container/ 10 presentational/ 11 12 checkout/ 13 cart.service.ts 14 container/ 15 presentational/ ? ? ?
  37. 1 features/ 2 shell/ products/ 3 4 product-detail/ 5 checkout/

    6 7 shared/ 8 store/ 9 global-checkout.store.ts services/ 10 11 checkout.service.ts 12 models/ product.models.ts 13
  38. 1 features/ 2 shell/ 3 products/ 4 product-detail/ 5 checkout/

    6 7 shared/ 8 store/ 9 global-checkout.store.ts 10 services/ 11 checkout.service.ts 12 models/ 13 product.models.ts
  39. 1 features/ 2 shell/ 3 products/ 4 product-detail/ 5 checkout/

    6 7 shared/ 8 store/ 9 global-checkout.store.ts 10 services/ 11 checkout.service.ts 12 models/ 13 product.models.ts
  40. 1 features/ 2 shell/ 3 products/ 4 product-detail/ 5 checkout/

    6 7 shared/ 8 store/ 9 global-checkout.store.ts services/ 10 11 checkout.service.ts 12 models/ 13 product.models.ts
  41. 1 features/ 2 shell/ 3 products/ 4 product-detail/ 5 checkout/

    6 7 shared/ 8 store/ 9 global-checkout.store.ts services/ 10 11 checkout.service.ts 12 models/ product.models.ts 13
  42. 1 2 3 4 5 6 7 8 9 10

    @Component({ selector: 'app-product-detail', imports: [RouterLink, ProductImageComponent, ProductInfoComponent], templateUrl: './product-detail.component.html', styleUrl: './product-detail.component.scss', providers: [ProductDetailStore] }) export class ProductDetailComponent implements OnInit { // ... }
  43. 1 2 3 4 5 6 7 8 9 10

    @Component({ selector: 'app-product-detail', imports: [RouterLink, ProductImageComponent, ProductInfoComponent], templateUrl: './product-detail.component.html', styleUrl: './product-detail.component.scss', providers: [ProductDetailStore] }) export class ProductDetailComponent implements OnInit { // ... }
  44. 1 shared/ 2 utils/ 3 helpers/ 4 common/ 5 misc/

    6 lib/ 7 date-utils.ts string-utils.ts 8 9 array-utils.ts 10 utils.ts 11 utils2.ts
  45. 1 shared/ 2 utils/ 3 helpers/ 4 common/ 5 misc/

    6 lib/ 7 date-utils.ts 8 string-utils.ts 9 array-utils.ts 10 utils.ts 11 utils2.ts
  46. 1 shared/ 2 utils/ 3 helpers/ 4 common/ 5 misc/

    6 lib/ 7 date-utils.ts 8 string-utils.ts 9 array-utils.ts 10 utils.ts 11 utils2.ts
  47. 1 shared/ 2 utils/ 3 helpers/ 4 common/ 5 misc/

    6 lib/ 7 date-utils.ts 8 string-utils.ts 9 array-utils.ts 10 utils.ts 11 utils2.ts
  48. 1 shared/ 2 utils/ 3 helpers/ 4 common/ 5 misc/

    6 lib/ 7 date-utils.ts 8 string-utils.ts 9 array-utils.ts 10 utils.ts 11 utils2.ts
  49. 1 shared/ 2 utils/ 3 helpers/ 4 common/ 5 misc/

    6 lib/ 7 date-utils.ts 8 string-utils.ts 9 array-utils.ts 10 utils.ts 11 utils2.ts
  50. 1 shared/ 2 utils/ 3 helpers/ 4 common/ 5 misc/

    6 lib/ 7 date-utils.ts string-utils.ts 8 9 array-utils.ts 10 utils.ts 11 utils2.ts
  51. ┌───────────────────────────────────────────────────────┐ │ Shell Cart (3) │ └───────────────────────────┬───────────────────────────┘ │ ┌────────────────────┼────────────────────┐ ▼

    ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Product │ │ Product │ │ Checkout │ │ │ │ Detail │ │ │ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │ ▼ │ │ ┌─────────────┐ │ └────────────▶│ Shared │◀────────────┘ │ cart · 3 │ └─────────────┘
  52. one route ──▶ features/<route>/ container/presentational/... too many routes? many routes

    ──▶ shared/ no route ──▶ the shell ──▶ one level up