Project Overview & Angular + Express Setup

Romaji to Kana Converter: Angular & Express

Chapter 1 · Project Overview & Angular + Express Setup

This is one of three courses building the exact same tool in three genuinely different architectures — a web app that takes romaji (Latin-alphabet-transliterated Japanese) text and converts it into hiragana and katakana. Romaji to Kana Converter: Astro and Romaji to Kana Converter: React & Next.js remain outlined; this course's own answer gives Angular its one real home across this site's entire Personal Multi-Technology Projects set, paired with a small Express API it doesn't otherwise have anywhere here.

What the App Actually Does

  • Convert romaji text — typed Latin-alphabet Japanese, like konnichiwa — into both hiragana (こんにちは) and katakana (コンニチワ).
  • Handle real Japanese-specific edge cases correctly — long vowels, the small っ (sokuon, doubled consonants), and particle exceptions (は pronounced "wa," へ pronounced "e") — covered in real depth in Chapter 3.
  • Ties directly into content already on this site — the existing Japanese-language lessons and the kanji tiles/reference-materials pages, both real, immediate practical uses for a working romaji-to-kana tool once it's live.

Full kanji conversion is explicitly out of scope for this course — a genuinely bigger, real dictionary-and-context-dependent problem (the same word in kana can map to several different kanji depending on meaning), deliberately deferred as a real future project of its own rather than something this course pretends to solve as a side effect of romaji conversion.

Why This Variant Commits to a Real Express Conversion Engine

The actual romaji-to-kana algorithm — a real character-mapping table plus the edge-case handling Chapter 3 covers — could genuinely run entirely inside the browser, with no backend involved at all. Both sibling courses in this trio treat that as a real, open question worth exploring directly:

CourseHow the client-vs-server question is treated
Romaji to Kana Converter: AstroAn open comparison — that course's own Chapter 5 is literally titled "Client-Side vs. Server-Side Conversion: Where Should the Logic Actually Run?"
Romaji to Kana Converter: React & Next.jsAlso open — that course's own Chapter 4 compares "An API Route for Conversion vs. Doing It Client-Side"
Romaji to Kana Converter: Angular & Express (this course)Decided from the outset — the conversion engine lives on a real, dedicated Express API from Chapter 5 onward, since giving Express a genuine backend role here is this course's own deliberate reason for existing

This isn't a claim that server-side conversion is objectively better — the sibling courses' own honest, comparative chapters are exactly where that real tradeoff gets explored. This course's own value is different: showing what a real Angular frontend calling a real, purpose-built Express API actually looks like, start to finish, since neither half of that pairing exists anywhere else in this project set.

Setting Up the Angular Frontend

This course targets current Angular (v22 at the time of writing) — standalone components, no NgModules, verified directly against Angular's own current documentation:

# Frontend npm install -g @angular/cli ng new romaji-converter --style=css cd romaji-converter

Routing and server-side rendering are both left off deliberately — neither flag is passed, and current Angular CLI defaults to skipping both unless explicitly requested. A single-page conversion tool genuinely has no second real route to navigate to, matching the same "no router needed" finding this site's own Personal Catalogue courses already reached for a similarly simple app.

Verified Against Angular's Own Current Documentation: File Names Changed
A freshly generated project's root component is no longer named app.component.ts. Current Angular's default "2025" file-naming style generates the shorter app.ts, with its template and styles in separate app.html and app.css files — a genuinely surprising change for anyone who learned Angular under the older .component.ts convention, confirmed directly against Angular's own current documentation rather than assumed from memory.

Every component generated in this project is standalone by default — current Angular removed the need to write standalone: true explicitly, since that's now the only option unless a component opts out with standalone: false. The app bootstraps with no root module at all:

// src/main.ts import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import { AppComponent } from './app/app'; bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));

Wiring Up HttpClient

Every other framework used across this project's own site so far has called the backend with a plain fetch(). Angular ships its own, dependency-injected HTTP client instead — real, idiomatic Angular, configured once at the application root:

// src/app/app.config.ts import { ApplicationConfig } from '@angular/core'; import { provideHttpClient } from '@angular/common/http'; export const appConfig: ApplicationConfig = { providers: [provideHttpClient()], };
A Real, Verified Aside on provideHttpClient()
Current Angular's own documentation notes that HttpClient is available for injection by default from Angular v21 onward, with no explicit provider required at all. provideHttpClient() is shown here anyway, since it's the explicit, always-correct setup regardless of exactly which version this ends up running against, and it's the natural place to add real features later — request interceptors, caching — via its own optional configuration arguments.

Setting Up the Express Backend

A sibling folder, exactly the same real pattern this site's own React-based courses already established for pairing a frontend with a small Node API:

# Backend, run from a sibling folder to romaji-converter mkdir romaji-converter-api && cd romaji-converter-api npm init -y npm install express cors dotenv npm install --save-dev nodemon
# .env PORT=4000

A minimal server confirms the backend is alive before any real conversion logic exists — Chapter 5 replaces this placeholder route with the real thing:

// 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}`));
CORS Is Needed Here Too
Angular's own dev server runs on port 4200 by default; Express runs on 4000. Two different origins, exactly the same real reason this site's own React-based courses needed cors() from their first chapter onward.

Confirming the Two Halves Talk to Each Other

A small, real service — Angular's own idiomatic pattern for anything that talks to a backend — calls the placeholder endpoint using the function-based inject() API rather than a constructor parameter:

// 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 --> <h1>Romaji to Kana Converter</h1> <p>Backend check: {{ pingResult }}</p>

Running npx nodemon server.js in one terminal and ng serve in the other, then visiting Angular's own dev server (typically http://localhost:4200), should show the real JSON response from Express rendered directly on the page — confirmation both halves of this stack are genuinely talking to each other before a single real conversion rule exists.

Where This Course Is Headed

A real romaji-to-kana mapping table (Chapter 2); the genuinely tricky edge cases — long vowels, sokuon, and particle exceptions (Chapter 3); structuring the tool properly across Angular services and components (Chapter 4); the real Express API this course exists to build, replacing today's placeholder route (Chapter 5); the actual input/output UI (Chapter 6); deployment (Chapter 7); and a capstone integrating this tool into the existing Astro-based site, right alongside the Japanese-language lessons and kanji pages it's meant to support (Chapter 8).

Hands-On Exercises

Exercise 1

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.

📄 View solution
Exercise 2

Run ng new in a separate scratch folder with no flags at all, and inspect the real generated file structure — confirm there's no routing module and no SSR-related files, and confirm the root component's own real file names match this chapter's own finding-box.

📄 View solution
Exercise 3

In your own words, explain why this specific course commits up front to a real Express-hosted conversion engine, while its two sibling courses treat the identical client-vs-server question as something to explore and compare within their own chapters instead.

📄 View solution

Chapter 1 Quick Reference

  • The shared app — romaji-to-hiragana/katakana conversion, kanji conversion deliberately deferred
  • Why this variant — gives Angular its one real home in this project set, paired with a small, purpose-built Express API
  • Decided, not explored — unlike its Astro and Next.js siblings, this course commits to server-side conversion from Chapter 1 onward
  • Current Angular (v22) — standalone by default, no NgModules, no routing/SSR unless explicitly requested
  • 2025 file-naming style — app.ts/app.html/app.css, not the older app.component.ts convention
  • HttpClient — Angular's own dependency-injected HTTP client, configured via provideHttpClient(), used in place of a raw fetch()
  • Next chapter: The Conversion Engine — a real romaji-to-kana mapping table