Lesson illustration

Creating a Strict Angular 17 Standalone Application

Welcome back. Your toolchain is now in place: Node 20, Angular CLI 17, and Angular DevTools. In this lesson you will create a clean Angular 17 workspace that deliberately matches the GCB-WMP direction: standalone components, strict TypeScript, routing enabled for future features, and no testing scaffolding for this focused learning track.

By the end, you will have a running local banking-application shell, a generated standalone dashboard component, and a concrete way to confirm that strict compilation is active.


Create a reproducible Angular 17 workspace

An Angular workspace is more than a folder containing frontend files. It is the unit that holds the application source, installed dependencies, CLI/build configuration, and—eventually—possibly multiple applications or shared libraries. For now, create one isolated local practice workspace. It does not need the company repository, backend, API keys, or Keycloak access.

Before generating, confirm that your terminal is using the expected CLI:

ng version

You should see Angular CLI 17.x.x and Node 20.x.x.

{"type":"reading","par_intro":"Read the official Angular CLI documentation to understand what `ng new` creates and why the standalone and strict options matter for this project.","par_directions":"In the **Description** section, read <span data-type=\"resource_reading_textrange\" data-resource-subitem-id=\"c1db4334\" data-range-start=\"Creates and initializes a new Angular application that is the default project for a new workspace.\" data-range-end=\"Subsequent applications that you generate in the workspace reside in the\">the workspace explanation</span>. Notice the distinction between the workspace root and the initial application generated in `src`.\n\nThen go to the **Options** table. Locate the `--standalone` and `--strict` rows and read <span data-type=\"resource_reading_textrange\" data-resource-subitem-id=\"4b7b7f90\" data-range-start=\"Creates an application based upon the standalone API, without NgModules.\" data-range-end=\"This setting helps improve maintainability and catch bugs ahead of time.\">those option descriptions</span>. Focus on the fact that these are project-generation decisions, stored in the generated configuration rather than temporary command-line behavior.","learning_duration":"7 minutes","url":"https://v17.angular.io/cli/new","title":"Angular - ng new","isV2":true,"blockId":"4db26534-f6a8-4925-a0f6-4c460250f57f","lessonId":"2264e65f-0c15-43b1-98cd-f4a837fc243d"}



Create the project from a directory where you keep local development work:

ng new gcb-wmp-lab \
  --routing \
  --style=scss \
  --standalone \
  --strict \
  --skip-tests \
  --package-manager=npm \
  --ssr=false \
  --defaults

If your terminal does not support the multi-line form, run the same command on one line:

ng new gcb-wmp-lab --routing --style=scss --standalone --strict --skip-tests --package-manager=npm --ssr=false --defaults

A few choices here are intentional:

ChoiceWhy it fits this course and GCB-WMP-style work
gcb-wmp-labA clearly separate local sandbox, not a substitute for the future company repository.
--routingPrepares the app for dashboard, accounts, transfers, and auth routes.
--style=scssRetains CSS familiarity while providing nesting, variables, and partials when they are useful.
--standaloneUses the Angular 17 component-first architecture required by the blueprint.
--strictEnables stronger TypeScript and Angular template checks to catch mismatches early.
--skip-testsKeeps generated test files out of this learning workspace, consistent with your requested course scope.
--ssr=falseStarts with a conventional client-rendered SPA, which matches the project blueprint.

The CLI will create the directory, install packages, and usually initialize a local Git repository. Let the install finish before proceeding.

Move into the workspace and start the development server:

cd gcb-wmp-lab
ng serve --open

The CLI compiles the application and opens:

http://localhost:4200/

Keep this terminal open. It is now watching your source files and rebuilding the application as you save changes. Stop the server later with Ctrl+C.


Understand the two generation decisions: standalone and strict

Angular applications are built from components. Historically, Angular grouped components through NgModule classes. The GCB-WMP blueprint instead uses the modern standalone API.

{"type":"video","title":"Getting Started with Standalone Components in Angular","learning_duration":141,"video_id":"x5PZwb4XurU","par_intro":"Watch “Getting Started with Standalone Components in Angular” from the Angular team for the conceptual shift from NgModules to self-contained components.","par_directions":"Watch <span data-type=\"resource_video_timerange\" data-resource-subitem-id=\"8ab713ac\" data-range-start=\"0\" data-range-end=\"106\">the standalone rationale</span> to see why components can be the primary organizational unit. Then watch <span data-type=\"resource_video_timerange\" data-resource-subitem-id=\"0d089b32\" data-range-start=\"167\" data-range-end=\"202\">component generation</span>, focusing on the generated `standalone: true` marker and the component-level `imports` array.\n\nThe video predates some Angular 17 template conveniences you will use later, but its architectural point remains central: a standalone component declares the template dependencies it needs.","video_duration":709,"isV2":true,"blockId":"f7226dd0-fd18-4d27-b85d-a46fcee4dd4f","lessonId":"2264e65f-0c15-43b1-98cd-f4a837fc243d"}



Standalone means explicit template dependencies

A standalone component is marked with:

standalone: true

Its decorator also owns an imports array. This array is not the same as TypeScript imports at the top of the file:

  • A TypeScript import makes a class, function, or type usable by the TypeScript file.
  • A component decorator’s imports makes Angular directives, pipes, and standalone components available in that component’s template.

This is one of the most important React-to-Angular adjustments. In React, importing a child component into a file is generally sufficient for JSX usage. In standalone Angular, you usually need:

  1. A TypeScript import of the child class.
  2. The child class listed in the parent component’s decorator imports.
  3. The child’s selector used in the parent template.

Angular’s explicit template dependency list makes it easier to see what a screen needs without navigating through a shared module. It also supports focused lazy loading later in the course.

Strict means compilation must prove more

The --strict option turns on TypeScript strictness and Angular’s stronger template checking. In the generated project, inspect the root tsconfig.json; you should find:

{
  "compilerOptions": {
    "strict": true
  }
}

You should also find Angular compiler settings that include strict template checking, commonly including:

{
  "angularCompilerOptions": {
    "strictTemplates": true
  }
}

Exact surrounding options can differ slightly between generated versions, but those strict settings are the important contract.

For banking software, this matters because a value that might be absent should not silently be treated as definitely present. For example, strict null checks reject this:

const referenceCode: string = null;

Likewise, strict template checking helps identify cases where a template tries to read a possibly absent field. It does not validate data received from an API at runtime, replace client-side form validation, or authorize a transfer. It gives you earlier feedback while writing the client code, where it is cheapest to correct a mismatch.

{
  "type": "exercise",
  "id": "12585648-62ca-42b4-98d6-667d2060fe76"
}

Add a small standalone dashboard component

The newly generated root component is already standalone. Now generate a second component and wire it into the application. This is a deliberately small vertical slice: no API call yet, just the structural pattern you will use for real dashboard widgets.

With ng serve still running, open a second terminal in the gcb-wmp-lab directory and run:

ng generate component features/dashboard/portfolio-status \
  --standalone \
  --skip-tests \
  --inline-template \
  --inline-style

The CLI creates portfolio-status.component.ts under the requested feature path. Replace its contents with:

import { Component } from '@angular/core';

@Component({
  selector: 'app-portfolio-status',
  standalone: true,
  template: `
    <section class="status-card" aria-labelledby="portfolio-status-heading">
      <h2 id="portfolio-status-heading">Portfolio status</h2>
      <p>Local Angular workspace is running.</p>
      <p>Mock account data will be connected in a later lesson.</p>
    </section>
  `,
  styles: [`
    .status-card {
      max-width: 42rem;
      padding: 1.25rem;
      border: 1px solid #c7d3e0;
      border-radius: 0.5rem;
      background: #ffffff;
      color: #172b4d;
    }
  `]
})
export class PortfolioStatusComponent {}

This component does not need anything in its decorator imports array because its template uses only ordinary HTML elements. Once it uses Angular directives, pipes, Material components, or other standalone components, you will add the relevant dependencies there.

Next, replace the contents of src/app/app.component.ts with:

import { Component } from '@angular/core';
import { PortfolioStatusComponent } from './features/dashboard/portfolio-status/portfolio-status.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [PortfolioStatusComponent],
  template: `
    <main class="app-shell">
      <h1>GCB-WMP Frontend Lab</h1>
      <p class="environment-label">Local development workspace</p>

      <app-portfolio-status></app-portfolio-status>
    </main>
  `,
  styles: [`
    .app-shell {
      max-width: 68rem;
      margin: 0 auto;
      padding: 2rem;
      font-family: Arial, sans-serif;
      background: #f5f8fb;
      min-height: 100vh;
    }

    .environment-label {
      color: #4a5d75;
    }
  `]
})
export class AppComponent {}

Save both files. The browser should rebuild automatically and display:

  • GCB-WMP Frontend Lab
  • Local development workspace
  • A bordered Portfolio status card

If the child component does not render, check these three items before changing anything else:

  1. The TypeScript import path points to the generated component file.
  2. PortfolioStatusComponent appears in the root component’s decorator imports array.
  3. The template selector is exactly <app-portfolio-status></app-portfolio-status>.

This concise pattern will recur throughout the project: a screen or shell component explicitly imports the visual building blocks used by its template.

{
  "type": "exercise",
  "id": "0296fa1d-5b8f-4fdb-bb66-06c9ee9f9b44"
}

Verify the application and its strict build

A development server is useful, but a production build is a separate verification step. In another terminal, still inside gcb-wmp-lab, run:

npm run build

A successful build demonstrates that TypeScript compilation, Angular template compilation, and bundling all complete under the strict configuration.

To see strict null checking in action, temporarily add this line just beneath the imports in app.component.ts:

const transferReference: string = null;

Save the file. The compiler should reject it because null is not assignable to string under strict null checking. Remove the line immediately afterward so the application returns to a successful state.

This small experiment is worth doing once: it makes strictness tangible. In later lessons, the errors will be more meaningful—possibly absent API fields, incompatible DTO shapes, invalid form values, and template expressions that make unsafe assumptions.

Now verify the runtime structure through Angular DevTools, which you configured in the previous lesson:

  1. Open http://localhost:4200/.
  2. Open browser DevTools.
  3. Select the Angular tab, then Components.
  4. Confirm that the component tree includes the root component and PortfolioStatusComponent.
  5. Select the child component and inspect its metadata.

This is your first confirmation that the browser is running an Angular component tree rather than merely rendering static HTML.

{
  "type": "exercise",
  "id": "c5718ab4-1bf6-40f9-836d-6ba0cf637e79"
}

Completion checkpoint

You have completed this lesson when all of the following are true:

  • A gcb-wmp-lab workspace exists locally.
  • ng version inside the workspace reports Angular 17.x.
  • ng serve --open runs the application at localhost:4200.
  • The application renders a root shell and a generated PortfolioStatusComponent.
  • Both components are standalone.
  • The root component lists PortfolioStatusComponent in its decorator imports.
  • tsconfig.json has "strict": true, and Angular strict template checking is enabled.
  • npm run build completes successfully after you remove the intentional null-assignment error.
  • Angular DevTools displays the root and child components.

You now have a strict, runnable Angular 17 SPA foundation rather than just an installed toolchain. Next, you will orient yourself inside this workspace: locating the bootstrap path, route configuration, providers, build configuration, and feature source files so that an unfamiliar enterprise Angular repository becomes navigable quickly.

Can't find a good explanation? Sign up and we'll make it for you