Migrate to RunxBuild today!! Deploy More while Spending Less

Calculate your savings
unxBuild

Angular First Steps: From ng new to a Deployed Build, With the Parts the Official Tutorial Leaves Out

Sean

Platform Writer

Sep 21, 2026
9 min read

The first steps in Angular are five commands and three concepts: install Node and the Angular CLI, run ng new to generate a project, run ng serve to see it, then learn what a component, a template and a service are, because everything in the framework is one of those. The official tutorial covers that well and stops at the development server. This guide keeps going to ng build, which produces a folder of static files, and to putting that folder on a host with a real URL, because an Angular app that only runs on localhost has not finished its first steps.

Angular First Steps: From ng new to a Deployed Build, With the Parts the Official Tutorial Leaves Out

Angular has a reputation for being heavy, and the reputation comes from its size as a framework rather than from the effort to start. Starting is a few minutes. What takes longer is understanding which of the many generated files you will actually touch, and this guide names them.

Table of contents

Step one: the toolchain

node --version        # an active LTS release; the CLI states the minimum
npm install -g @angular/cli
ng version

The CLI is the whole developer experience: it generates projects and files, runs the dev server, runs tests, and produces the production build. Learning its subcommands is more useful than memorising the framework’s API, because the CLI writes the boilerplate that the API requires.

Step two: generate and run

ng new my-app --style=css --routing
cd my-app
ng serve --open

The prompts ask about stylesheet format and server-side rendering; plain CSS and no SSR are the right first answers. ng serve compiles the application, starts a dev server on port 4200, and rebuilds on every file change. The page it opens is the generated placeholder, and the next step is finding the three files that produce it.

Step three: the three files that matter

A generated project has a few dozen files. For the first week, you edit three.

  • src/app/app.component.ts is the root component: a class with a decorator that names its selector, its template and its styles. State lives here as class properties; behaviour lives here as methods.
  • src/app/app.component.html is the template: HTML with Angular’s syntax for binding to the class. {{ title }} prints a property, (click)="save()" calls a method, [disabled]="busy" binds an attribute, and the built-in control flow @if and @for render conditionally and in loops.
  • src/app/app.routes.ts maps URL paths to components. Add a route here, generate a component for it, and the app has a second page.

Newer projects are standalone by default, meaning components declare their own imports rather than belonging to a module, which removes the NgModule layer that used to be the fourth file. If a tutorial you are following talks about app.module.ts, it predates that change and the concepts still apply; the wiring is just in the component now.

Step four: a component and a service

The two building blocks, generated by the CLI so the boilerplate is right.

ng generate component tasks
ng generate service tasks

A component owns a piece of the screen. A service owns data and logic that more than one component needs, and it is provided through dependency injection, so a component asks for it in its constructor rather than creating it.

// src/app/tasks.service.ts
import { Injectable, signal } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class TasksService {
  readonly tasks = signal<string[]>([]);

  add(task: string) {
    this.tasks.update(list => [...list, task]);
  }
}
// src/app/tasks/tasks.component.ts
import { Component, inject } from '@angular/core';
import { TasksService } from '../tasks.service';

@Component({
  selector: 'app-tasks',
  standalone: true,
  templateUrl: './tasks.component.html',
})
export class TasksComponent {
  private readonly service = inject(TasksService);
  tasks = this.service.tasks;
  draft = '';

  add() {
    if (this.draft.trim()) {
      this.service.add(this.draft.trim());
      this.draft = '';
    }
  }
}
<!-- src/app/tasks/tasks.component.html -->
<input [(ngModel)]="draft" placeholder="New task" />
<button (click)="add()">Add</button>

@for (task of tasks(); track task) {
  <p>{{ task }}</p>
} @empty {
  <p>No tasks yet.</p>
}

Signals are the current reactive primitive: a value that components read by calling it, and that triggers a re-render when it changes. The [(ngModel)] two-way binding needs FormsModule in the component’s imports array; the compiler error when you forget is explicit. Add <app-tasks /> to the root template, or a route for it, and the feature is on screen.

Step five: talking to an API

The service is also where HTTP lives. Provide the HTTP client once in the application config, inject it in the service, and return observables or convert them to signals.

// src/app/app.config.ts
import { provideHttpClient } from '@angular/common/http';
export const appConfig = { providers: [provideRouter(routes), provideHttpClient()] };

// in a service
private readonly http = inject(HttpClient);
load() {
  return this.http.get<string[]>('/api/tasks');
}

The API URL is the first thing that differs between development and production. Use a relative path and a dev-server proxy so that /api forwards to your backend locally, and let the host route /api to the backend in production. That avoids the environment-file dance that most tutorials introduce and never resolve.

Step six: build, and understand what came out

ng build
# output in dist/my-app/browser/
#   index.html, main-*.js, polyfills-*.js, styles-*.css, assets/

The production build is a folder of static files with hashed filenames. There is no server in it. That is the property that makes deployment simple: anything that serves static files can serve an Angular app, provided it does one thing correctly. Angular’s router handles URLs in the browser, so a visitor who loads /tasks directly must be served index.html rather than a 404, and the application then renders the route. Every static host has a setting for this, usually called a single-page-app fallback or a rewrite of all paths to the index.

Two build settings worth knowing early: the budgets in angular.json fail the build when the bundle exceeds a size, which is a feature, and ng build --configuration development produces an unminified build for debugging a production-only problem.

Step seven: deploy the folder

Put the repository on GitHub, connect it to a static host, set the build command to ng build and the output directory to dist/my-app/browser, and enable the SPA fallback. The host builds on every push, serves the files from a CDN, and issues a certificate for the domain. That is the last first step: the application is at a URL you can send to someone.

If the app talks to an API you also wrote, that backend is a separate service, deployed on its own, with the static host or a rewrite rule sending /api to it. Keeping the two apart is the right architecture from the beginning, because the frontend is a folder of files and the backend is a process, and they scale, deploy and fail differently.

How this fits the rest of the stack

The deployment half of this is short on a platform built for it. A static site on RunxBuild builds from the repository with ng build, serves dist/my-app/browser with the SPA fallback switched on, and issues the certificate for the domain; a rewrite sends /api to whichever service runs the backend. The RunxBuild hosting calculator shows the static site with 120GB of bandwidth included next to that backend and its database, which is the full cost of an Angular app with a real API behind it.

Useful related references:

FAQ

What do I need installed to start with Angular?

An active LTS release of Node.js, npm, and the Angular CLI installed globally with npm install -g @angular/cli. The CLI generates the project, runs the dev server, runs tests and produces the production build, so it is the one tool to learn first.

What is the difference between a component and a service in Angular?

A component owns a piece of the screen: a class with state and methods, a template, and styles. A service owns data and logic shared across components, provided through dependency injection so components ask for it rather than creating it. HTTP calls and application state belong in services.

What does ng build produce?

A folder of static files under dist/, containing index.html, hashed JavaScript and CSS bundles, and assets. There is no server. Any static host can serve it, as long as it is configured to serve index.html for every path so the client-side router can handle deep links.

Why does refreshing a page on my deployed Angular app give a 404?

Because the host tried to find a file at that path and there is none; Angular’s router handles paths in the browser. Enable the host’s single-page-app fallback or a rewrite of all paths to index.html, and the application will load and render the route.

How do I connect an Angular app to a backend API in production?

Use relative API paths such as /api/tasks. In development, configure the CLI’s proxy so /api forwards to the local backend. In production, have the static host rewrite /api to the backend service. This avoids hard-coding environment-specific URLs into the build.

#angular first steps#getting started with angular#ng new#angular tutorial beginners#deploy angular app