Project Overview & Next.js Setup
Romaji to Kana Converter: React & Next.js
Chapter 1 · Project Overview & Next.js Setup
This is the third of three real, working variants of the same converter — a web tool that takes typed romaji (Latin-alphabet Japanese) and converts it live to hiragana and katakana. The Astro variant, completed first, is the site's own current framework and the most direct "could genuinely ship tomorrow" story. The Angular & Express variant committed, from its own Chapter 1, to a real, dedicated Express backend paired with a framework this site had no other home for. This course's own real reason for existing is different again — and it's worth naming precisely before writing a single line of the conversion logic itself.
The Shared Spec
The core feature is unchanged from both sibling courses: a real, verified gojūon-plus-yōon
romaji-to-kana mapping table, real handling for long vowels, sokuon (small っ), and the
は/へ/を particle exceptions, and a live input box producing both a hiragana and a katakana
output as the user types. Full kanji conversion is explicitly out of scope for this course —
a genuinely bigger, dictionary-and-context-dependent problem, honestly flagged in this
project's own tracking (project_issues.md P2) as a real future sub-project in its
own right, not a missing feature of this one.
This Variant's Own Real Angle
Both sibling courses had to make an explicit architectural choice about where the frontend and backend actually live. Astro's own default is a single project that can serve both static pages and, once opted in per route, real on-demand server code — but Chapter 1 of that course deliberately left the question of whether this specific feature should use that capability open until its own Chapter 5. Angular has no server story of its own at all, so that course committed to a real, separate Express backend from the very first chapter, specifically because pairing Angular with a purpose-built backend was that course's own stated reason to exist.
Next.js's own real, defining feature sits between those two positions, and it's the reason this variant is worth building at all: a single Next.js project can hold both the React UI and real server-side API endpoints — Route Handlers, covered properly in Chapter 4 — without ever needing a second framework, a second process, or a second deployment target the way the Angular course's Express backend does. There's still a genuine architectural decision to make about where the conversion logic should actually run — that question isn't pre-answered here either, and Chapter 4 addresses it directly, informed by the real, measured verdict Chapter 5 of the Astro course already reached for the identical feature. What's already decided, and what this chapter's own setup reflects, is that whichever way that decision goes, it never requires leaving this one project.
| Variant | Frontend/backend relationship | Client-vs-server decision |
|---|---|---|
| Astro | One project; on-demand server routes are opt-in per page | Left open in Ch.1, resolved with a real measured benchmark in Ch.5 |
| Angular & Express | Two separate projects, two separate processes | Committed to a real server from Ch.1 — that pairing is the course's own reason to exist |
| React & Next.js | One project; UI and API routes are both native to it | Left open in this chapter, resolved directly in Ch.4 |
A Real, Current Next.js Setup
Scaffolding a fresh project with the real, current CLI (verified directly against Next.js's own documentation, current release 16.3.5):
TypeScript, ESLint, and the App Router are all real current defaults — the flags above just
make that explicit rather than relying on an interactive prompt. Tailwind is deliberately
declined (--no-tailwind): both sibling courses style this converter with plain
CSS matching the site's own established dark-tool palette, and Chapter 5's own UI work keeps
that convention rather than introducing a styling system neither variant otherwise uses.
Turbopack ships enabled by default and is left as-is.
romaji-converter-nextjs/ ├── src/ │ └── app/ │ ├── layout.tsx │ ├── page.tsx │ ├── globals.css │ └── api/ │ └── ping/ │ └── route.ts ← added below, the first real Route Handler ├── public/ ├── package.json ├── tsconfig.json └── next.config.ts
A Real, Working Placeholder Route
Before Chapter 2's own conversion engine exists to call, it's worth confirming the Route
Handler mechanism itself actually works end to end — the same discipline both sibling courses
already applied to their own first real server call. A Route Handler lives at
app/api/<path>/route.ts, exporting an async function named after the HTTP
method it handles:
Verified with a real request against the local dev server:
GET Route Handler with no explicit caching configuration is
dynamic by default — it genuinely re-runs on every request rather than being
statically cached the way it was before that change. That matters here: a future kanji/vocabulary
lookup route (the natural home for Chapter 6's own Redis caching idea, once kanji conversion is
picked up as a real future project) would need to know its own responses aren't silently frozen
at build time without opting in explicitly via a revalidate export — this variant's
plain conversion route in Chapter 4 benefits from the identical default, with zero extra
configuration needed to keep it live.
Route Handlers use the real Web Request/Response APIs directly —
request.json() to read a JSON body, Response.json(...) to return one —
rather than a framework-specific request/response object the way Express's own
req/res pair works. That's the exact shape Chapter 4's own
POST /api/convert route will use once the conversion engine exists to call.
Hands-On Exercises
Scaffold the project exactly as shown above, run npm run dev, and confirm the placeholder /api/ping route responds correctly both from a browser tab and from a real curl request.
Add a second placeholder route, POST /api/echo, that reads a JSON body of the shape {"message": "..."} and returns it back unchanged. Confirm it with a real POST request, and explain why this route needs request.json() where /api/ping needed nothing from the request at all.
Using this chapter's own compare-table, explain in your own words why the Angular & Express course genuinely needed two separate projects while this course doesn't — and why that difference is a real structural one, not just a stylistic preference.
📄 View solutionChapter 1 Quick Reference
- Shared spec unchanged — real romaji-to-kana conversion, kanji explicitly deferred (
project_issues.mdP2) - This variant's own angle — one Next.js project holds both the UI and real server-side API routes, with no second process required either way the Ch.4 decision goes
- Setup — TypeScript, App Router, ESLint, plain CSS (no Tailwind), verified against Next.js 16.3.5's own current
create-next-appdefaults - A real, working placeholder route —
GET /api/ping, using the real WebRequest/ResponseAPIs directly - Verified finding —
GETRoute Handlers are dynamic by default since Next.js 15, with no extra config needed to keep them live