Fullstack CourseLearn by building
Back to roadmap

Week 1 — Node.js, Express & NestJS HTTP foundations

Understand the Node runtime and Express request flow before learning the structure Nest adds — then ship Notes P1 as this week’s mini-project.

End-of-week mini-project · practice only

Link Shortener API (Nest HTTP, in-memory)

Build a URL shortener with Nest: create short codes, redirect visitors, and count hits — all in memory, no database yet.

Definition

A standalone Nest HTTP service that turns long URLs into short codes and 302-redirects visitors, exercising the full Week 1 request pipeline without any persistence.

In simpler words

Make your own tiny bit.ly. You POST a long URL, get a short code back, and hitting the code redirects you while the service counts clicks.

Concepts covered this week

Node.js runtime, modules & npm
Scaffold with the Nest CLI; wire npm scripts (start:dev, build) and read package.json.
Async work & the event loop
A non-blocking setInterval sweep expires old links without freezing request handling.
Express routing, middleware & errors
Warm up with a 15-line Express version of the redirect route, then rebuild it the Nest way.
Nest architecture & CLI
nest g module/controller/service generates the LinksModule slice.
Modules
LinksModule groups the controller + providers and is imported by AppModule.
Dependency injection
Inject LinksService and a CodeGenerator provider through the constructor.
Decorators
@Module, @Controller, @Injectable, @Get/@Post, @Param, @Body describe the wiring.
Controllers
LinksController maps POST /links, GET /:code, and the JSON admin routes.
Services
LinksService holds the in-memory Map and all create/lookup/stats logic.
Request pipeline
A logger middleware, an ApiKeyGuard, a ValidationPipe, and a NotFound filter run in order.
REST API + Postman / curl
Exercise every route from Postman/curl and confirm status codes (201, 302, 404).

Deliverables

  • LinksModule + LinksController + LinksService generated via the Nest CLI
  • POST /links (validated body) returning a unique short code; GET /:code issuing a 302 redirect
  • GET /api/links (list) and GET /api/links/:code/stats (hit count)
  • A request-logger middleware, an ApiKeyGuard on admin routes, a global ValidationPipe, and a filter that returns clean 404 JSON

Build guide

  1. Scaffold the projectRun nest new link-shortener, then nest g module/controller/service links. Enable a global ValidationPipe in main.ts.
  2. Contrast with raw ExpressWrite a throwaway Express route that redirects /:code so you feel what Nest abstracts (routing, middleware order, error handling).
  3. Model the data in memoryIn LinksService keep a Map<string, { url; hits; createdAt }>. Add a CodeGenerator provider returning a short base62 id.
  4. Create + validateCreateLinkDto with @IsUrl(); POST /links returns 201 with { code, shortUrl }. Reject unknown fields with whitelist/forbidNonWhitelisted.
  5. Redirect + countGET /:code looks up the map, increments hits, and 302-redirects to the original URL; unknown codes throw NotFoundException.
  6. Protect admin routesAdd an ApiKeyGuard reading an x-api-key header and apply it to the list/stats routes to practice guards.
  7. Expire in the backgroundUse setInterval in onModuleInit to sweep links older than N minutes — non-blocking event-loop work.
  8. Test the whole surfaceDrive create → redirect → stats → list → 404 from Postman/curl and verify each status code.

Acceptance checklist

- [ ] Nest CLI scaffold with LinksModule/Controller/Service
- [ ] POST /links validates the body and returns a unique code
- [ ] GET /:code redirects (302) and increments the hit counter
- [ ] Unknown code returns a clean 404 via an exception filter
- [ ] Admin routes protected by a guard; logger middleware runs first
- [ ] Every route verified from Postman/curl

Stretch goals

  • Add custom aliases (POST a desired code) and reject collisions with 409.
  • Return a QR-code image for a short link.
  • Hide the in-memory Map behind an interface so Week 2 can drop in Postgres.

Tips

  • Keep the store behind a service boundary — Week 2 will replace the Map with a repository.
  • Redirect status is 302 (or 301 for permanent); return JSON only on the /api routes.