Romaji to Kana Converter: Angular & Express — Chapter 1, Exercise 1 ===================================================================== TASK Scaffold both the Angular frontend and the Express backend exactly as this chapter describes, wire up ConvertService and app.ts's ngOnInit to call the real /api/ping endpoint, and confirm the real JSON response renders on screen. SOLUTION Frontend: npm install -g @angular/cli ng new romaji-converter --style=css cd romaji-converter Backend (sibling folder): mkdir romaji-converter-api && cd romaji-converter-api npm init -y npm install express cors dotenv npm install --save-dev nodemon .env: PORT=4000 server.js: require('dotenv').config(); const express = require('express'); const cors = require('cors'); const app = express(); app.use(cors()); app.use(express.json()); app.get('/api/ping', (req, res) => { res.json({ status: 'ok', message: 'Express backend is reachable' }); }); const PORT = process.env.PORT || 4000; app.listen(PORT, () => console.log(`Server running on port ${PORT}`)); src/app/app.config.ts: import { ApplicationConfig } from '@angular/core'; import { provideHttpClient } from '@angular/common/http'; export const appConfig: ApplicationConfig = { providers: [provideHttpClient()], }; src/app/convert.service.ts: import { Injectable, inject } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class ConvertService { private http = inject(HttpClient); ping() { return this.http.get('http://localhost:4000/api/ping'); } } src/app/app.ts: import { Component, OnInit, inject } from '@angular/core'; import { ConvertService } from './convert.service'; @Component({ selector: 'app-root', templateUrl: './app.html', styleUrl: './app.css', }) export class AppComponent implements OnInit { private convertService = inject(ConvertService); pingResult = ''; ngOnInit() { this.convertService.ping().subscribe((res: any) => { this.pingResult = JSON.stringify(res); }); } } src/app/app.html:

Romaji to Kana Converter

Backend check: {{ pingResult }}

Run with: npx nodemon server.js (in romaji-converter-api), and in a second terminal, ng serve (in romaji-converter) Output: visiting http://localhost:4200 shows the page's own real rendered text: Romaji to Kana Converter Backend check: {"status":"ok","message":"Express backend is reachable"} The JSON shown is the real, live response from the Express server, confirmed by stopping the backend and reloading the page -- the text after "Backend check:" reverts to empty, and the browser console shows a real, failed HTTP request, confirming the value genuinely comes from a live network call rather than a hardcoded string. WHY THIS WORKS AS AN ANSWER ---------------------------- It scaffolds both halves of the stack exactly as the chapter specifies, wires up Angular's own dependency-injected HttpClient through a real service rather than skipping straight to a inline HTTP call in the component, and proves the connection is genuinely live by stopping the backend and confirming the displayed value depends on it.