Skip to content

🧩 Efficiently organize small to mid-sized Angular apps with practical insights into project architecture.

Notifications You must be signed in to change notification settings

bodnya29179/Angular-Project-Architecture

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 

Repository files navigation

Angular Project Architecture

Small & Middle Architecture

.
└── πŸ“ project
    β”œβ”€β”€ πŸ“ scripts
    β”‚   β”œβ”€β”€ <file name>.js
    β”‚   └── ...
    β”‚
    β”œβ”€β”€ πŸ“ src
    β”‚   β”œβ”€β”€ πŸ“ app
    β”‚   β”‚   β”œβ”€β”€ πŸ“ pages
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ <page name>
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ components
    β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ services
    β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ interfaces
    β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ store
    β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ actions
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <actions group name>.actions.ts
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ effects
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <effects group name>.effects.ts
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ reducers
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <reducer name>.reducer.ts
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ selectors
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <selectors group name>.selectors.ts
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚   β”‚   └── state.ts
    β”‚   β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”‚   └── <page name>.module.ts
    β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ app.component.html
    β”‚   β”‚   β”œβ”€β”€ app.component.spec.ts
    β”‚   β”‚   β”œβ”€β”€ app.component.ts
    β”‚   β”‚   β”œβ”€β”€ app-routing.module.ts (optional)
    β”‚   β”‚   └── app.module.ts
    β”‚   β”‚
    β”‚   β”œβ”€β”€ πŸ“ shared
    β”‚   β”‚   β”œβ”€β”€ πŸ“ components
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ <component name>
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <component name>.component.html
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <component name>.component.scss
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <component name>.component.spec
    β”‚   β”‚   β”‚   β”‚   └── <component name>.component.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ directives
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ <directive name>
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <directive name>.directive.spec.ts
    β”‚   β”‚   β”‚   β”‚   └── <directive name>.directive.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ services
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ <service name>
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <service name>.service.spec.ts
    β”‚   β”‚   β”‚   β”‚   └── <service name>.service.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ pipes
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ <pipe name>
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <pipe name>.pipe.spec.ts
    β”‚   β”‚   β”‚   β”‚   └── <pipe name>.pipe.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ guards
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ <guard name>
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <guard name>.guard.spec.ts
    β”‚   β”‚   β”‚   β”‚   └── <guard name>.guard.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ interceptors
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ <interceptor name>
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <interceptor name>.interceptor.spec.ts
    β”‚   β”‚   β”‚   β”‚   └── <interceptor name>.interceptor.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ utils
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ <util name>
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <util name>.util.spec.ts
    β”‚   β”‚   β”‚   β”‚   └── <util name>.util.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ interfaces
    β”‚   β”‚   β”‚   β”œβ”€β”€ <interface name>.interface.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ types
    β”‚   β”‚   β”‚   β”œβ”€β”€ <type name>.type.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ enums
    β”‚   β”‚   β”‚   β”œβ”€β”€ <enum name>.enum.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ constants
    β”‚   β”‚   β”‚   β”œβ”€β”€ <constant name>.const.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ store
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ actions
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <actions group name>.actions.ts
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ effects
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <effects group name>.effects.ts
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ reducers
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <reducer name>.reducer.ts
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ selectors
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ <selectors group name>.selectors.ts
    β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   β”‚
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚   └── state.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ shared.module.ts
    β”‚   β”‚   └── public-api.ts
    β”‚   β”‚
    β”‚   β”œβ”€β”€ πŸ“ assets
    β”‚   β”‚   β”œβ”€β”€ πŸ“ animations
    β”‚   β”‚   β”‚   β”œβ”€β”€ <file name>.json
    β”‚   β”‚   β”‚   └── ...
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ fonts
    β”‚   β”‚   β”‚   └── πŸ“ <font name>
    β”‚   β”‚   β”‚       β”œβ”€β”€ <font name>-Regular.ttf
    β”‚   β”‚   β”‚       β”œβ”€β”€ <font name>-Bold.ttf
    β”‚   β”‚   β”‚       β”œβ”€β”€ <font name>-Light.ttf
    β”‚   β”‚   β”‚       β”œβ”€β”€ <font name>-Italic.ttf
    β”‚   β”‚   β”‚       └── ...
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ i18n
    β”‚   β”‚   β”‚   β”œβ”€β”€ <language code>.json
    β”‚   β”‚   β”‚   └── ...
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ icons
    β”‚   β”‚   β”‚   └── <file name>.svg
    β”‚   β”‚   β”‚   └── ...
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ images
    β”‚   β”‚   β”‚   β”œβ”€β”€ <file name>.png
    β”‚   β”‚   β”‚   β”œβ”€β”€ <file name>.jpg
    β”‚   β”‚   β”‚   β”œβ”€β”€ <file name>.jpeg
    β”‚   β”‚   β”‚   └── ...
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ sprite
    β”‚   β”‚   β”‚   └── svg-sprite.svg
    β”‚   β”‚   β”‚
    β”‚   β”‚   └── favicon.ico
    β”‚   β”‚
    β”‚   β”œβ”€β”€ πŸ“ environments
    β”‚   β”‚   β”œβ”€β”€ πŸ“ endpoints
    β”‚   β”‚   β”‚   β”œβ”€β”€ <api name>-endpoints.ts
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.ts
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ environment.ts
    β”‚   β”‚   └── environment.prod.ts
    β”‚   β”‚
    β”‚   β”œβ”€β”€ πŸ“ styles
    β”‚   β”‚   β”œβ”€β”€ πŸ“ mixins
    β”‚   β”‚   β”‚   β”œβ”€β”€ <file name>.scss
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.scss
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ variables
    β”‚   β”‚   β”‚   β”œβ”€β”€ <file name>.scss
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.scss
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ buttons
    β”‚   β”‚   β”‚   β”œβ”€β”€ <file name>.scss
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.scss
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ inputs
    β”‚   β”‚   β”‚   β”œβ”€β”€ <file name>.scss
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.scss
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ πŸ“ placeholders
    β”‚   β”‚   β”‚   β”œβ”€β”€ <file name>.scss
    β”‚   β”‚   β”‚   β”œβ”€β”€ ...
    β”‚   β”‚   β”‚   └── index.scss
    β”‚   β”‚   β”‚
    β”‚   β”‚   β”œβ”€β”€ reset.scss
    β”‚   β”‚   β”œβ”€β”€ styles.scss
    β”‚   β”‚   └── index.scss
    β”‚   β”‚
    β”‚   β”œβ”€β”€ index.html
    β”‚   └── main.ts
    β”‚
    β”œβ”€β”€ .editorconfig
    β”œβ”€β”€ .eslintrc.json
    β”œβ”€β”€ .gitignore
    β”œβ”€β”€ angular.json
    β”œβ”€β”€ karma.conf.js
    β”œβ”€β”€ proxy.conf.json (optional)
    β”œβ”€β”€ package.json
    β”œβ”€β”€ package-lock.json
    β”œβ”€β”€ tsconfig.app.json
    β”œβ”€β”€ tsconfig.json
    β”œβ”€β”€ tailwind.config.js
    └── README.md

Additional notes

The index.ts files

The index.ts allows Angular developers to keep all related things closely packed together, so they don’t need to bother about the source file name. This helps to reduce the size of introductory statements.

Avoid using business logic in the component

Many developers mix the components and business logic, resulting in a complex and untidy mess that is difficult to comprehend. Hence, it is important to follow Angular development best practice guidelines and keep the logic separate from your components.

The testing process of UI and components differ from Logic Testing.

Different services for Business Logic are used to improve code reusability and quality. Having logic in a separate service will allow you to use it in multiple components. This would result in a reduction of build size and also lesser code.

The core folder

Description:
In many projects, the core folder is often used to store services and components that are considered fundamental to the application's core functionality, such as authentication services, global data services, and application-wide components like the main navigation bar.

General usage:
The key here is to maintain consistency and clarity in your project structure. If the distinction between core and shared doesn't serve your project's needs, it's perfectly fine to eliminate the core folder and place everything in the shared or other relevant folders. Ultimately, the goal is to have a structure that makes it easy for developers to understand and navigate the codebase.

Architectural choice:
The distinction between core and shared doesn't provide any meaningful separation in the project, it's perfectly valid to opt for a flatter structure.

Arguments for not using the core folder in the project:

  • Simplicity and Consistency:
    Having fewer folders and a flatter structure can make the project easier to navigate and understand for both new and existing developers. It simplifies the mental model required to locate and manage different parts of the code.

  • Reduced Redundancy:
    Placing all shared components, services, and other elements in a single shared folder can eliminate the redundancy introduced by maintaining both a core and a shared folder. This reduction in duplication can lead to cleaner and more maintainable code.

  • Flexibility in Organizing:
    With a flat structure, you have the flexibility to organize your code based on logical modules or features rather than forcing components into predefined core and shared categories. This can be especially helpful as your project evolves and its structure naturally adjusts to new requirements.

  • Easier Refactoring:
    Without the core folder, you won't have to worry about moving code between core and other folders during refactorings or changes. This can save time and effort, as well as reduce the risk of breaking the application.

  • Clarity in Responsibility:
    In many cases, the line between what constitutes core functionality and what belongs in shared can become blurred. Placing everything in shared emphasizes that all components and services are equally important and contributes to a more balanced understanding of the codebase.

  • Ease of Onboarding:
    For new team members, a simpler folder structure can speed up the onboarding process. They won't need to learn the nuances of distinguishing between core and shared items.

  • Maintainability:
    As the project grows, a flat structure can help prevent the creation of sprawling subfolders. This can lead to better maintainability and improved performance in version control systems.

Summary
In summary, eliminating the core folder simplifies the project structure, reduces redundancy, and allows for greater flexibility in organizing and maintaining the codebase. It aligns with the principle of simplicity and can lead to a more efficient development process.

About

🧩 Efficiently organize small to mid-sized Angular apps with practical insights into project architecture.

Topics

Resources

Stars

Watchers

Forks