Skip to content

EngrAhmadofficial/seconde-technical-test

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

URL Shortener

A secure URL shortener: users authenticate to create and list short links; anyone can open a short URL and receive an HTTP 302 redirect to the original destination. Built as a full-stack reference implementation with Docker-first workflows.


Project overview

Aspect Description
Access control Sign up / sign in (JWT). Creating and listing links requires a valid bearer token.
Public behaviour GET /{slug} resolves a stored link and redirects with 302 to the target URL.
Frontend Root / is the auth experience; /dashboard manages links.
Operations PostgreSQL, Prisma migrations, and services are orchestrated with Docker Compose.

Tech stack

Layer Technology
API NestJS 11, TypeScript
ORM / DB access Prisma ORM 7, @prisma/adapter-pg + pg
Database PostgreSQL 15
Auth JWT (@nestjs/jwt), Passport JWT strategy, bcrypt password hashing
Validation class-validator, class-transformer
Frontend Next.js (App Router), React 19, Tailwind CSS 4, Axios
Deployment Docker, Docker Compose

Features

  • User auth — Registration and login; passwords hashed with bcrypt; API access via JWT bearer tokens.
  • Dashboard — Create short links and view your list (full short URLs shown for copy/open).
  • Slug generation6-character alphanumeric codes; uniqueness enforced in the database with collision retry.
  • Public redirect — Unauthenticated GET /:slug302 to the stored original URL; clear 404 message when the slug does not exist.
  • Dockerized stack — API, web UI, and database run from a single Compose file; backend waits for DB health before starting.

Getting started

Prerequisites

1. Clone and start the stack

From the repository root:

docker-compose up --build
Service URL / port
Frontend http://localhost:3001
Backend API http://localhost:3000
PostgreSQL localhost:5432 (credentials in docker-compose.yml)

The backend service depends on the database healthcheck and, on startup, runs npx prisma migrate deploy before npm run start:dev, so a fresh clone usually comes up with schema applied automatically.

2. Apply database migrations (explicit step)

If you need to run migrations without starting the full API (e.g. empty DB, CI, or troubleshooting):

docker-compose run --rm backend npx prisma migrate deploy

Use the same command after pulling migration changes. Ensure the db service is reachable (e.g. docker-compose up -d db first, or run while the stack is up).

3. Environment variables (reference)

Variable Where Purpose
DATABASE_URL Backend PostgreSQL connection string (Compose sets this to host db)
JWT_SECRET Backend Symmetric secret for signing JWTs
PORT Backend HTTP port (default 3000)
NEXT_PUBLIC_API_URL Frontend Browser-visible API base URL (e.g. http://localhost:3000)

Running tests

End-to-end tests exercise: register → login → create URL → list URLs → public redirect (302).

With Compose (database must be available to the backend container):

docker-compose run --rm backend npm run test:e2e

The test:e2e script runs prisma migrate deploy then Jest. For local runs without Docker, set DATABASE_URL and run npm run test:e2e from the backend/ directory.


API reference (summary)

Method Path Auth Description
POST /auth/register No Create account; returns { access_token }
POST /auth/login No Obtain { access_token }
POST /urls Bearer JWT Create a short link
GET /urls Bearer JWT List current user’s links
GET /:slug No Public redirect (302) to original URL

Technical decisions

  1. Prisma 7 and the PostgreSQL driver adapter
    Prisma 7 expects a driver adapter for direct TCP access. This project uses @prisma/adapter-pg with the pg driver so the client talks to PostgreSQL efficiently while keeping migrations and schema in Prisma.

  2. JWT + Passport strategy
    Authentication is stateless: after login or register, the client stores the JWT and sends Authorization: Bearer <token> on protected routes. The server validates the token with a Passport JWT strategy and attaches the user context for URL ownership checks.

  3. Route layout: no global /api prefix and root-level redirects
    JSON endpoints live at /auth and /urls on the same origin as the redirect handler. There is no app.setGlobalPrefix('api'), so public short links can stay as GET /{slug} at the root. Reserved slugs (e.g. auth, urls, health) are excluded at generation time so random codes do not shadow real routes.

  4. Validation at the edge
    DTOs with class-validator keep request bodies predictable and return consistent validation errors before business logic runs.

  5. CORS
    The API enables CORS for browser calls from the Next.js app when origins differ during development.


Project structure (high level)

.
├── backend/           # NestJS API, Prisma schema & migrations
├── frontend/          # Next.js App Router UI
├── docker-compose.yml # db, backend, frontend
└── README.md

Author

Muhammad Ahmad Tariq

For questions or review feedback related to this technical test repository, reach out via the channels you use with the maintainer.

About

Fullstack URL Shortener built with NestJS, Next.js, and PostgreSQL for the Seconde technical assessment.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors