The 2016 Coaching Center Trap
If you visit coaching centers in Ameerpet (Hyderabad) or Kothrud (Pune), trainers will tell you to install jQuery inside an Angular project and paste Bootstrap CDN scripts into index.html. If you do this in a modern technical interview, you will fail immediately.
Directly mutating the DOM with jQuery destroys Angular's change detection, causes memory leaks, and demonstrates that a developer does not understand modern frontend architecture. Angular in its latest releases is standalone, fast, and does not require external script hacks.
Here is how you build a real-world, production-ready Angular application from terminal initialization to cloud deployment.
Step 1: Scaffolding with Standalone Architecture
Ensure you have Node.js 20 LTS installed. Initialize a new project with the Angular CLI without installing global dependencies:
npx @angular/cli@latest new developer-dashboard --routing --style=scss --ssr=false
cd developer-dashboard
npm start
Your local dev server will boot up at http://localhost:4200. Look at the generated src/app/ directory. Notice there is no app.module.ts. Modern Angular boots directly from src/main.ts via bootstrapApplication(AppComponent, appConfig).
Step 2: Configuring HTTP Client in appConfig
To fetch data from external APIs, you need the Angular HTTP client. Instead of importing HttpClientModule into a root module, configure it cleanly inside src/app/app.config.ts:
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient, withFetch } from '@angular/common/http';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient(withFetch())
]
};
The withFetch() feature flag tells Angular to use the browser's native fetch API instead of legacy XMLHttpRequest, improving performance and memory usage.
Step 3: Creating a Typesafe API Service
Create a service to query GitHub's public API. Run the CLI generator:
npx ng g s services/github
Open src/app/services/github.service.ts and implement modern dependency injection using inject():
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
export interface GithubRepo {
id: number;
name: string;
description: string | null;
stargazers_count: number;
html_url: string;
language: string | null;
}
@Injectable({
providedIn: 'root'
})
export class GithubService {
private readonly http = inject(HttpClient);
private readonly apiUrl = 'https://api.github.com';
getUserRepos(username: string): Observable<GithubRepo[]> {
return this.http.get<GithubRepo[]>(
`${this.apiUrl}/users/${username}/repos?sort=updated&per_page=6`
);
}
}
Step 4: Building the UI with Signals and Native Control Flow
Now create a standalone component to display the developer's repositories:
npx ng g c components/repo-list
Open src/app/components/repo-list/repo-list.component.ts. Use Angular Signals for reactive state handling:
import { Component, inject, signal, OnInit } from '@angular/core';
import { GithubService, GithubRepo } from '../../services/github.service';
@Component({
selector: 'app-repo-list',
standalone: true,
templateUrl: './repo-list.component.html',
styleUrl: './repo-list.component.scss'
})
export class RepoListComponent implements OnInit {
private readonly github = inject(GithubService);
// Reactive state signals
repos = signal<GithubRepo[]>([]);
isLoading = signal<boolean>(true);
errorMessage = signal<string | null>(null);
ngOnInit(): void {
this.loadRepositories('angular');
}
loadRepositories(username: string): void {
this.isLoading.set(true);
this.errorMessage.set(null);
this.github.getUserRepos(username).subscribe({
next: (data) => {
this.repos.set(data);
this.isLoading.set(false);
},
error: (err) => {
this.errorMessage.set('Failed to fetch repositories. Rate limit exceeded or user not found.');
this.isLoading.set(false);
}
});
}
}
Next, open the template file repo-list.component.html. Replace obsolete *ngIf and *ngFor structural directives with native control flow:
<div class="repo-container">
<h2>Featured Repositories</h2>
@if (isLoading()) {
<div class="status-box loading">Fetching GitHub repositories...</div>
} @else if (errorMessage()) {
<div class="status-box error">{{ errorMessage() }}</div>
} @else {
<div class="repo-grid">
@for (repo of repos(); track repo.id) {
<article class="repo-card">
<h3>
<a [href]="repo.html_url" target="_blank" rel="noopener noreferrer">
{{ repo.name }}
</a>
</h3>
<p>{{ repo.description || 'No description provided.' }}</p>
<div class="meta">
<span class="badge">{{ repo.language || 'Plain Text' }}</span>
<span class="stars">★ {{ repo.stargazers_count }}</span>
</div>
</article>
} @empty {
<p class="empty">No public repositories found for this account.</p>
}
</div>
}
</div>
Add clean modern styles in repo-list.component.scss:
.repo-container {
max-width: 900px;
margin: 2rem auto;
padding: 0 1rem;
font-family: system-ui, -apple-system, sans-serif;
}
.repo-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
gap: 1.5rem;
margin-top: 1rem;
}
.repo-card {
background: #1e293b;
color: #f8fafc;
padding: 1.25rem;
border-radius: 8px;
border: 1px solid #334155;
display: flex;
flex-direction: column;
justify-content: space-between;
h3 a {
color: #38bdf8;
text-decoration: none;
&:hover { text-decoration: underline; }
}
p {
font-size: 0.9rem;
color: #94a3b8;
margin: 0.75rem 0;
}
.meta {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.85rem;
}
}
Step 5: Production Build and Zero-Cost Cloud Deployment
Do not deploy development builds. Compile your project using the production optimization pipeline:
npm run build
Angular compiles your TypeScript, inlines critical CSS, tree-shakes unused libraries, and outputs production assets to dist/developer-dashboard/browser/. Total bundle size will typically be under 80KB gzipped.
You can deploy this directory to Vercel, Netlify, or Cloudflare Pages completely free:
# Deploy with Vercel CLI
npx vercel deploy --prod ./dist/developer-dashboard/browser
Conclusion
Building modern Angular applications does not require complex module wiring or outdated scripts. By utilizing standalone components, the inject() function, reactive Signals, and native template control flow, you produce lean, high-performance web applications ready for real production environments.
