Roadmap › AngularJS (1.x) — Legacy › Module: Fundamentals
Lessons in this course (13)

4. AngularJS (1.x) project folder structure — with sample files

Basic★ Must knowLesson 4 of 13

AngularJS apps (2010–2021) usually have no CLI; files are loaded by <script> tags or bundled with Gulp/Grunt/webpack. Two common layouts: by type (small apps) and by feature (recommended by the John Papa style guide).

text
shop-web/                              (often inside an ASP.NET MVC 5 project's Scripts/app folder)
├── index.html                         ng-app="shopApp", <div ng-view>, script tags
├── app/
│   ├── app.module.js                  angular.module('shopApp', ['ngRoute'])
│   ├── app.config.js                  $routeProvider routes, $httpProvider interceptors
│   ├── app.constants.js               API base URL
│   ├── core/
│   │   ├── auth.interceptor.js        adds Authorization header
│   │   └── logger.service.js
│   ├── products/                      feature folder
│   │   ├── products.controller.js     ProductsController (controllerAs syntax)
│   │   ├── products.service.js        productService — $http calls
│   │   ├── products.html              view template
│   │   └── product-card.directive.js  (or .component.js in 1.5+)
│   └── orders/ …
├── content/css/site.css
├── lib/angular/angular.min.js, angular-route.min.js   (or node_modules + bundler)
└── tests/ (Karma + Jasmine)
js
// app/app.module.js
angular.module('shopApp', ['ngRoute']);

// app/app.config.js
angular.module('shopApp')
  .constant('API_URL', '/api')
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider
      .when('/products', { templateUrl: 'app/products/products.html', controller: 'ProductsController', controllerAs: 'vm' })
      .otherwise({ redirectTo: '/products' });
  }]);

// app/products/products.controller.js
angular.module('shopApp').controller('ProductsController', ['productService', function (productService) {
  var vm = this;
  vm.products = [];
  vm.loading = true;
  productService.getAll()
    .then(function (products) { vm.products = products; })
    .catch(function () { vm.error = 'Could not load products'; })
    .finally(function () { vm.loading = false; });
}]);
html
<!-- index.html -->
<html ng-app="shopApp">
<body>
  <div ng-view></div>
  <script src="lib/angular/angular.min.js"></script>
  <script src="lib/angular/angular-route.min.js"></script>
  <script src="app/app.module.js"></script>
  <script src="app/app.config.js"></script>
  <script src="app/products/products.service.js"></script>
  <script src="app/products/products.controller.js"></script>
</body>
</html>

<!-- app/products/products.html -->
<p ng-if="vm.loading">Loading…</p>
<ul><li ng-repeat="p in vm.products track by p.id">{{ p.name }} — {{ p.price | currency:'₹' }}</li></ul>

Script order matters: the module file first, then everything that registers into it.