Welcome to the second entry in the Angular 2025 Guide! In Part 1, we explored how to master standalone components, the backbone of modern Angular development. Now that you know how to build in a modular, component-first way, itโs time to look at the big picture: how to structure your entire project to support this new paradigm.
Spoiler: if youโre still organizing your app by modules or by type (components here, services there)... yeah, itโs time for an intervention.
Weโll cover smart folder architecture with real examples from the base project repo (angular-example-app), that will guide this series.
Organizing by feature โ the core idea
In a features-first structure, your app is split by capabilities, not by type. A feature contains its own UI, logic, routes, and maybe even state.
Hereโs a simplified snapshot:
.
โโโ app/
โโโ features/
โโโ authentication/
โ โโโ pages/
โ โ โโโ log-in
โ โ โโโ register
โ โ โโโ my-account
โ โโโ services
โ โโโ types
โ โโโ authentication.routes.ts
โโโ home/
โ โโโ home.component.html
โ โโโ home.component.scss
โ โโโ home.component.ts
โโโ pokemon/
โโโ components/
โ โโโ catch-animation
โ โโโ pokedex
โ โโโ pokemon-battlefield
โ โโโ pokemon-card
โ โโโ pokemon-image
โ โโโ pokemon-search-input
โโโ pages/
โ โโโ my-pokemon
โ โโโ pokemon-detail
โโโ services
โโโ types
โโโ pokemon.routes.ts
Real example: see src/app/features in the Angular Example App.
Why this works:
- Each feature is self-contained.
- Teams can work independently on features.
- Easier to refactor, lazy-load, or even remove.
No more shared/ โ use core/ instead
The old shared/ folder was a magnet for chaos. Sometimes you'd even dump everything there โjust in caseโ it might be reused. It became the graveyard of your architecture.
.
โโโ core/
โโโ components
โโโ constants
โโโ directives
โโโ enums
โโโ guards
โโโ interceptors
โโโ pipes
โโโ providers
โโโ services
โโโ tokens
โโโ types
โโโ validators
You'll find this setup under src/app/core.
Everything there should be agnostic and not related to any concrete feature. In this architecture, if you find some functionality reused in multiple places, make it a feature.
You treat reused logic like a first-class citizen, not an afterthought in a utils.ts.
โก Standalone + route-based loading = faster apps
Angular 17+ is built for this. With standalone components and route-level providers, your features load quickly and stay isolated.
export const appRoutes: Route[] = [
{
path: ROOT_PATHS.home,
component: HomeComponent,
},
{
path: AUTHENTICATION_PATHS.base,
loadChildren: async () =>
import('./features/authentication/authentication.routes').then(
(module_) => module_.AUTHENTICATION_ROUTES,
),
},
{
path: ROOT_PATHS.myPokemon,
component: MyPokemonComponent,
canActivate: [authenticationGuard],
},
{
path: POKEMON_PATHS.base,
loadChildren: async () =>
import('./features/pokemon/pokemon.routes').then((module_) => module_.POKEMON_ROUTES),
},
{ path: '404', component: Error404Component },
{ path: '**', redirectTo: '404' },
];
This means:
- No need for a HomeModule
- Smaller bundles on load
- No leaking providers globally
Example: See how app.routes.ts are used.
Summary โ Feature First All the Way
- Feature-based structure is the default in 2025. Modules are optional.
- The core/ folder replaces shared/, organized by responsibility.
- Everything reused = a feature โ give it its folder and routes if needed.
- Standalone + feature providers = better performance and clean DI.
- Avoid libs/ or mega service folders. Keep it flat, clear, and focused.
โ Whatโs Next: The Signal Way - Modern State and Data Flow
Up next in the series: weโll dive into Signals, httpResource, and local state management.
Have questions or want to see a specific example? Drop an issue in the repo or reach out!
I hope youโve learned something new from all of this. If you think this might help others, please hit the like button so more people can find it. โค๏ธ
Got thoughts or questions? Drop a comment โ I'd love to respond!
Top comments (0)