How to define a top-level folder structure for your Angular project

VenuThomas
NeST Digital
Published in
9 min readFeb 16, 2023

So far, I’m working on a new project at Angular. My many fellow project workers asked me for Angular’s help. So I thought of writing an article for them. In this article, let me show you the perfect directory and file structure for any angular project.

For this article I am using Angular CLI in version 15.0.4 with Node in version 18.12.0

Let’s begin by creating an Angular project, for that we use the following command (you can use the CMD or terminal of your choice). In this case, I will use the terminal in the Visual Studio Code

ng new <project-name>

For Example

ng new MyNewProject

While execute this command, Angular CLI will ask you some questions.

  1. Would you like to add Angular routing? (y/n)… This step is important as it asks whether you want to add routing to your app. This file is important as it lets us manage routes in our app. My recommendation is to add it.
  2. Which stylesheet format would you like to use? … It also asks you which stylesheet format you would like to add. My recommendation is to use SCSS. This type of stylesheet has all the perks of CSS, including the perks of SASS that. As stated on its official website is an CSS with superpowers.

NOTE: While using the integrated git terminal. The creation command does NOT ask whether you want the project’s routing or style format. The default is to create them.

Once these steps have been completed, your project will continue to create. Now let’s create the project structure (from a new project).

Directory structure sections

Now describing the 7 most important sections of how the project is structured (each section is optional). it would be the following:

  • Core module — The CoreModule assumes the role of the root AppModule. It is responsible for sustaining global services. In all likelihood, these services are HTTP services for communicating with an API. It is also used for storing guards, models and other global dependencies, such as http interceptor and global error controller. To maintain a well-structured and written codebase, we will group the typescript entities into their own folder within the core module (classes, enums, interfaces).
  • Data module — We will store everything concerning the application data, such as API services, services for platform usage cases.
  • Layout directory — The Layout directory contains the components declared on the AppModule. This directory contains page-level content components like menu, common header and footer. (This is within the Root Module)
  • Shared module — The Shared Module contains code that will be used in all feature modules, it is used solely to maintain common components, pipes and directives throughout the application.
  • Modules directory — In this section, you will find all the modules which will help to structure the application, such as authentication, registration, login and management modules.
  • Styles — The styles directory serves to store SCSS style sheets for the application. It can contain themes, Bootstrap, angular material and any other style.
  • Media directory — The Media directory can store support files for the app, things such as app logo, icons, images, and so on.

Generation of modules and directories.

Then we will generate all the abovementioned directories. Remember that all these commands must be executed from the root of your app.

Main module (core module)

ng g m core

Once the module is created, add it to the import of the main module of the app.module.ts application (remember to do the corresponding import)

// src\app\app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CoreModule } from '@core/core.module';

import { BrowserAnimationsModule } from '@angular/platform-browser/animations'

@NgModule({
declarations: [
AppComponent
],

imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
CoreModule
],

providers: [],

bootstrap: [AppComponent]
})
export class AppModule { }

NOTE: At this stage, I recommend adding the BrowserAnimationsModule this module allows integration of browser animations.

I assure you that if you have used angular you have found the typical nesting, something that is quite difficult to sustain. if you have found that when you are importing a module, function or class you need to:

import {<moduleName> } from '../../../<moduleFileName>'

That is an utter mistake to use. as well as broadening the lines of code and making it insatiable and illegible. This doesn’t look good. Now we’re correcting that. Well, that’s quite simple. we must edit the tsconfig.json file and you must make sure that in baseUrl is “./src”, this so that when adding the shortness it takes them from src and in paths, we will add @app, @core, @shared, @components, @env, @module, @data and @layout.

{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@app/*": ["app/*"],
"@core/*": ["app/core/*"],
"@shared/*": ["app/shared/*"],
"@components/*": ["app/shared/components/*"],
"@env/*": ["environment/*"],
"@modules/*": ["app/modules/*"],
"@data/*": ["app/data/*"],
"@layout/*": ["app/layout/*"]
}
}
}

Now, the difference is that when you import a resource, you can do it like this:

import { <moduleName> } from '@modules/<moduleFileName>';

like in AppModule

import { CoreModule } from './core/core.module';

to

import { CoreModule } from '@core/core.module';

Data module

ng generate module data

OR

ng g m data

Once you have created this module, you need to create the following directories inside the data module.

  • Constants — Directory for storing application constants such as static data, page paths, APIs paths, and so on. Tactics, page routes, apis routes, etc.
  • Interfaces — These models contain Angular application models defined by entities.
  • Mocks — This is particularly helpful for testing, but you can also use it to retrieve fictitious data until the back-end is installed. The simulation directory contains all the simulated files in our application.
  • Services\api — The services folder is one of the core module’s main folders, since it provides the various call services to the endpoints of one or more Rest APIs.

Layout directory

mkdir src/app/layout

This directory can be used to define the basic elements of a web application. In that case, we will define the application’s header, footer and main page. Don’t forget that these commands are executed from the root of your application.

ng g c layout/mainpage
ng g c layout/header
ng g c layout/footer

INFO: “ng g c” means short of “ng generate component”

You can use the — skip-tests argument in commands, this argument indicates that these components will be generated without their test files(like <yourfile>.spec.ts). You can remove this argument and create that file if you want.

At this point it is important that you check that your application has imported the generated components into the declarations of the main module file of app.module.ts.

src\app\app.module.ts

If the components have been successfully imported into your app.module.ts. Go to app.component.html and remove all its contents, just make sure that you have the application router:

<!-- src\app\app.component.html -->

<router-outlet></router-outlet>

Now we are going to add our header and footer components to the main page of the application.

<!-- src\app\layout\mainpage\mainpage.component.html -->

<!-- Header -->
<app-header></app-header>

<!-- Page -->
<router-outlet></router-outlet>

<!-- Footer -->
<app-footer></app-footer>

NOTE: The header and footer selectors will be named according to the name used to create these components.

Shared module

ng g m shared

Once this module is created, you need to add it to the import of the main module of the app.module.ts application.

src\app\app.module.ts

The shared module is a great place to import and export the FormsModule and ReactiveFormsModule for use with forms in the application. It is also good for the HttpClientModule and RouterModule to do HTTP requests and move between application routes.

This module’s directory may look something like this:

NOTE: The use of barrel files may be very useful for reducing imports.

// src\app\shared\shared.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
declarations: [],
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
RouterModule
],

exports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
HttpClientModule,
RouterModule
]
})
export class SharedModule { }

Module directory

This directory contains modules which are separate from one another. This allows Angular to load only the module it needs to view the query, saving bandwidth and speeding up the entire app. Since Lazy Loading is used.

To do that, each module should have its own routing, which is a loadChildren route resource defined in the AppRoutingModule.

For our application we are going to generate three modules, a home (dashboard), contact and about.

ng g m modules/<module-name> - routing

For example:

ng g m modules/home - routing
ng g m modules/about - routing
ng g m modules/contact - routing

Whenever we create a module, it is necessary to import our SharedModule model as illustrated below.

src\app\modules\home\home.module.ts

Media directory

The Media directory can store support files for the app, things such as app logo, icons, images, and so on.

mkdir media

Generate a main page component for each module

Now we are going to create the main pages of each module (Home (Dashboard), About, Contact).

ng g c modules/<module-name>/pages/<page-name>

For example:

ng g c modules/home/pages/home
ng g c modules/about/pages/about
ng g c modules/contact/pages/contact

NOTE: Once we create our main page elements, we need to define the path for the main element of the created module. In the routing of each module

src\app\modules\home\home-routing.module.ts

Loading modules using LazyLoading

To inject our modules created by lazy loading:

//src\app\app-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MainpageComponent } from '@layout/mainpage/mainpage.component';
import { AboutModule } from '@modules/about/about.module';
import { ContactModule } from '@modules/contact/contact.module';
import { HomeModule } from '@modules/home/home.module';

const routes: Routes = [

{
path: '',
component: MainpageComponent,
children: [
{
path: 'home',
loadChildren: () => import('@modules/home/home.module').then((m):typeof HomeModule => m.HomeModule)
},
{
path: 'about',
loadChildren: () => import('@modules/about/about.module').then((m):typeof AboutModule => m.AboutModule)
},
{
path: 'contact',
loadChildren: () => import('@modules/contact/contact.module').then((m):typeof ContactModule => m.ContactModule)
}
]
}
];

@NgModule({

imports: [RouterModule.forRoot(routes, {useHash: true})],
exports: [RouterModule]
})

export class AppRoutingModule { }

Configuration for recharging our routes

This setup is important because it will allow us to correctly reload our application’s pages and paths when our project is in production or hosting.

In the main application example module app.module.ts in the provider section, we add the strategy for reloading routes:

src\app\app.module.ts

Also, in the app-routing.module.ts file in the import section, add the following

src\app\app-routing.module.ts

Verification

At this point we can check if the application is functioning properly. we can execute one of the following commands

ng serve
ng serve -o
Home Page
About Page
Contact Page

Our app is functioning properly, I CONGRATULATE YOU!! 👏

Other considerations

When I generate a new module, it contains two folders, one for pages and the other for components. The page directory contains the components which act as the pages of our module. As the component directory contains components that can be reused on the pages of our module (example: titles, buttons, loaders etc.).

To produce them, you can use this command:

ng g c modules/<module-name>/components/<component-name>

There is no general rule with respect to the creation of a folder structure in Angular, especially in large projects. The structure will change enormously according to the project’s characteristics. The general idea in this article is to maintain an orderly and coherent application that is explained on its own to the extent possible.

Thank you for reading this article! ❤️

I uploaded this source to git : https://github.com/venuthomas/AngularFileStructure

Remember first that you need to have everything set up (Angular and Node installed) in order for it to work properly.

If you would like to ask me questions, please feel free! I’ll always have my mailbox open. Whether you have a question or would like to simply say hello. I will do my utmost to respond!

--

--