The Angular CLI generates the project, and unlike most scaffolding it is meant to be kept: you will use it every day for components, services and builds.
npm install -g @angular/cli
ng new my-appIt asks a few questions. The ones that matter: stylesheet format (SCSS is a
superset of CSS and costs nothing to choose), and server-side rendering — say no
unless you know you need it, since it can be added later with ng add @angular/ssr.
What it generated
src/
├── app/
│ ├── app.ts the root component
│ ├── app.config.ts application-wide providers
│ └── app.routes.ts the route table
├── environments/ build-time configuration
├── index.html one element, and it is not a div
├── main.ts the entry point
└── styles.scss global styles
angular.json build configuration
tsconfig.json TypeScript, plus Angular's compiler optionsHow the application starts
<body>
<app-root></app-root>
</body>import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { App } from './app/app';
bootstrapApplication(App, appConfig)
.catch((err) => console.error(err));bootstrapApplication is where the root NgModule used to be. Two arguments: the
root component, and the configuration.
app.config.ts
export const appConfig: ApplicationConfig = {
providers: [Everything the whole application needs, in one flat array — the router, HTTP, and any global service that is not registered from its own file.
Nothing here nests, and the order does not matter, because a provider is
looked up by token rather than by walking up a component tree. That is the difference from React's
stack of <Provider> components in main.tsx, where order matters
whenever one consumes another.
Note also what is not in it: the app's four stateful services.
providedIn: 'root' registers them from their own files, so adding one does not mean
editing this file.
angular.json
Build configuration. The parts you will actually edit:
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"src/styles.scss"
]Global stylesheets, in order — a third-party framework first, your overrides
second, so yours win without !important.
Also here: assets, the budgets that fail a build when a bundle grows,
and fileReplacements, which is how the environment file is swapped per configuration.
Three tsconfigs
tsconfig.json holds the shared settings; tsconfig.app.json and
tsconfig.spec.json extend it for the application and the tests. The split exists so test
types are not in scope when building the app.
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
},strictTemplates is the one worth knowing about. It type-checks
your templates against your components — misspell product().nmae and the build fails,
naming the file and line. Leave it on. A template is code, and this is what makes the compiler treat
it as such.
The commands
ng serve # dev server on :4200, reloads on save
ng build # production build into dist/
ng test # unit tests
ng generate component foo # scaffold — `ng g c foo` for short
ng generate service bar
ng update # upgrade Angular across a major versionng update deserves a mention. Angular ships migrations: it does
not just bump versions, it rewrites your code for breaking changes. That is how a project moves from
*ngIf to @if, or from decorators to signal inputs, without a manual sweep.
It is the strongest practical argument for the framework being opinionated.
The naming convention
A file is kebab-case, its class is PascalCase, its selector is prefixed:
product-card.ts exports ProductCard with selector
app-product-card. The prefix is configured once in angular.json and keeps
your components from colliding with HTML elements or a library's.
What is next
The TypeScript Angular leans on hardest — which is a short list, and not the one most tutorials cover.