AngularJSProject Structure

Project Structure

When you create a new Angular project with the CLI, it generates a well-organized directory structure. Understanding every file and folder will help you navigate large projects confidently and know exactly where to put new code.

Let's explore the structure of a freshly scaffolded Angular 17+ project with standalone components.

Top-Level Directory Overview

Text
my-angular-app/
├── .angular/            # Angular CLI cache (git-ignored)
├── .vscode/             # VS Code settings (optional)
├── node_modules/        # npm dependencies (git-ignored)
├── public/              # Static assets (Angular 17+)
│   └── favicon.ico
├── src/                 # Your application source code
│   ├── app/             # Application code (components, services, etc.)
│   ├── assets/          # Images, fonts, JSON files (older Angular)
│   ├── index.html       # Root HTML page
│   ├── main.ts          # Application entry point
│   └── styles.css       # Global CSS styles
├── .editorconfig        # Editor formatting rules
├── .gitignore
├── angular.json         # Angular CLI workspace configuration
├── package.json         # npm dependencies and scripts
├── package-lock.json    # Exact dependency versions
├── tsconfig.json        # Base TypeScript configuration
├── tsconfig.app.json    # TypeScript config for the app
└── tsconfig.spec.json   # TypeScript config for tests
The src/ Directory

Everything you write lives inside src/. Here is what each file does:

File

Purpose

src/index.html

The single HTML file served to the browser. Contains <app-root> where Angular mounts.

src/main.ts

Entry point — bootstraps the Angular application.

src/styles.css

Global styles applied across the entire app.

src/app/

Your feature code: components, services, routes, etc.

public/favicon.ico

Browser tab icon (Angular 17+ puts public assets here).

HTML
<!-- src/index.html -->
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>MyAngularApp</title>
    <base href="/" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="icon" type="image/x-icon" href="favicon.ico" />
  </head>
  <body>
    <app-root></app-root>  <!-- Angular renders here -->
  </body>
</html>

TS
// src/main.ts — bootstraps the app
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';

bootstrapApplication(AppComponent, appConfig)
  .catch((err) => console.error(err));
The src/app/ Directory

Text
src/app/
├── app.component.ts         # Root component (class)
├── app.component.html       # Root component template
├── app.component.css        # Root component styles
├── app.component.spec.ts    # Root component unit tests
├── app.config.ts            # Application-level providers (DI config)
└── app.routes.ts            # Route definitions

TS
// src/app/app.component.ts
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css',
})
export class AppComponent {
  title = 'my-angular-app';
}

TS
// src/app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
  ],
};

TS
// src/app/app.routes.ts
import { Routes } from '@angular/router';

export const routes: Routes = [
  // Define your routes here
  // { path: 'home', component: HomeComponent },
];
Recommended Feature-Based Structure

As your app grows, organize code into feature folders. Each feature folder contains all the code related to one feature or domain:

Text
src/app/
├── core/                    # Singleton services, guards, interceptors
│   ├── services/
│   │   ├── auth.service.ts
│   │   └── api.service.ts
│   ├── guards/
│   │   └── auth.guard.ts
│   └── interceptors/
│       └── auth.interceptor.ts
│
├── shared/                  # Reusable components, pipes, directives
│   ├── components/
│   │   ├── button/
│   │   └── modal/
│   ├── pipes/
│   │   └── truncate.pipe.ts
│   └── directives/
│       └── tooltip.directive.ts
│
├── features/                # Feature modules / pages
│   ├── home/
│   │   ├── home.component.ts
│   │   ├── home.component.html
│   │   └── home.component.css
│   ├── products/
│   │   ├── product-list/
│   │   │   ├── product-list.component.ts
│   │   │   └── product-list.component.html
│   │   ├── product-detail/
│   │   │   ├── product-detail.component.ts
│   │   │   └── product-detail.component.html
│   │   └── product.service.ts
│   └── auth/
│       ├── login/
│       └── register/
│
├── models/                  # TypeScript interfaces and types
│   ├── user.model.ts
│   └── product.model.ts
│
├── app.component.ts
├── app.config.ts
└── app.routes.ts
Note
This core / shared / features pattern is the most widely used Angular project structure in enterprise apps. Some teams also call it the SCAM pattern (Single Component Angular Module) or simply feature-based architecture.
angular.json — The Configuration Hub

angular.json is the workspace configuration file. It controls how the CLI builds, serves, and tests your project:

JSON
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "my-angular-app": {
      "projectType": "application",
      "schematics": {
        "@schematics/angular:component": {
          "style": "css",
          "standalone": true
        }
      },
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:application",
          "options": {
            "outputPath": "dist/my-angular-app",
            "index": "src/index.html",
            "browser": "src/main.ts",
            "polyfills": ["zone.js"],
            "tsConfig": "tsconfig.app.json",
            "styles": ["src/styles.css"],
            "assets": [{ "glob": "**/*", "input": "public" }]
          }
        }
      }
    }
  }
}
tsconfig.json — TypeScript Configuration

JSON
// tsconfig.json — base config
{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "strict": true,              // enables all strict type checks
    "noImplicitOverride": true,
    "noPropertyAccessFromIndexSignature": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "skipLibCheck": true,
    "isolatedModules": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,  // required for @Component, @Injectable, etc.
    "moduleResolution": "bundler",
    "target": "ES2022",
    "module": "ES2022",
    "lib": ["ES2022", "dom"]
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true    // type-check component templates
  }
}
Tip
strictTemplates: true enables full TypeScript type checking inside HTML templates — catching bugs like passing the wrong type to an @Input. Always leave this enabled.
package.json — Scripts and Dependencies

JSON
{
  "name": "my-angular-app",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test"
  },
  "dependencies": {
    "@angular/animations": "^17.3.0",
    "@angular/common": "^17.3.0",
    "@angular/compiler": "^17.3.0",
    "@angular/core": "^17.3.0",
    "@angular/forms": "^17.3.0",
    "@angular/platform-browser": "^17.3.0",
    "@angular/router": "^17.3.0",
    "rxjs": "~7.8.0",
    "zone.js": "~0.14.3"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^17.3.0",
    "@angular/cli": "^17.3.0",
    "@angular/compiler-cli": "^17.3.0",
    "@types/jasmine": "~5.1.0",
    "jasmine-core": "~5.1.0",
    "karma": "~6.4.0",
    "typescript": "~5.4.2"
  }
}
Environment Files

Angular uses environment files for configuration that differs between development and production (API URLs, feature flags, analytics keys, etc.):

Text
src/app/environments/
├── environment.ts           # development defaults
└── environment.prod.ts      # production overrides (swapped at build time)

TS
// src/app/environments/environment.ts
export const environment = {
  production: false,
  apiUrl: 'http://localhost:3000/api',
  analyticsKey: '',
};

// src/app/environments/environment.prod.ts
export const environment = {
  production: true,
  apiUrl: 'https://api.myapp.com',
  analyticsKey: 'UA-XXXXXXXX',
};

TS
// Usage in a service
import { environment } from '../environments/environment';

@Injectable({ providedIn: 'root' })
export class ApiService {
  private baseUrl = environment.apiUrl;  // automatically correct per build
}
File Naming Conventions

File type

Naming convention

Example

Component

kebab-case.component.ts

user-profile.component.ts

Template

kebab-case.component.html

user-profile.component.html

Styles

kebab-case.component.css/scss

user-profile.component.scss

Test

kebab-case.component.spec.ts

user-profile.component.spec.ts

Service

kebab-case.service.ts

user.service.ts

Guard

kebab-case.guard.ts

auth.guard.ts

Pipe

kebab-case.pipe.ts

truncate.pipe.ts

Directive

kebab-case.directive.ts

highlight.directive.ts

Model/Interface

kebab-case.model.ts

user.model.ts

Route config

kebab-case.routes.ts

products.routes.ts

Note
The Angular CLI automatically applies these naming conventions when you use ng generate. Following them makes your codebase predictable and easy to navigate.
Key Takeaways
  • src/main.ts bootstraps the app; src/index.html is the HTML shell

  • src/app/ holds all application code organized by feature

  • angular.json configures how the CLI builds and serves the app

  • tsconfig.json enables strict TypeScript and Angular template type checking

  • Feature-based structure (core/shared/features) scales well for large apps

  • Environment files separate config for development and production builds

  • Follow kebab-case.type.ts naming — the CLI does this automatically