Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Production-grade REST API for a blogging platform, built with TypeScript, Express 5, and PostgreSQL — featuring JWT auth, RBAC, cursor pagination, and OpenAPI documentation.

Notifications You must be signed in to change notification settings

devxsameer/blog-api

Open more actions menu

Repository files navigation

📝 Blog API – Production-Grade REST Backend

A modern, scalable, and production-ready REST API for a Markdown-based blogging platform.

This project demonstrates real-world backend engineering practices including authentication, authorization, modular architecture, cursor pagination, security hardening, and clean API design — built with TypeScript, Express 5, PostgreSQL, Drizzle ORM, and Zod.

⚡ Designed as a portfolio-grade backend to showcase job-ready backend skills.


🚀 Features

🔐 Authentication & Security

  • JWT access tokens (short-lived)
  • Refresh tokens via HTTP-only cookies
  • Secure logout & token rotation
  • Role-based access control (USER / AUTHOR / ADMIN)
  • Rate limiting on sensitive routes
  • Security headers via Helmet
  • Proper CORS for multiple frontends

✍️ Blogging System

  • Markdown-based posts
  • Draft / Published / Archived states
  • SEO-friendly slugs
  • Cursor-based pagination (no OFFSET issues)
  • View counting with deduplication
  • Like system with optimistic counters
  • likedByMe support for authenticated users

💬 Comments

  • Nested comments (replies)
  • Cursor pagination
  • Ownership & admin moderation policies

🏷️ Tags

  • Normalized tag system
  • Many-to-many post ↔ tags
  • Popular tags endpoint
  • Safe deduplication & normalization

🧱 Architecture & DX

  • Modular feature-based structure
  • Clean separation of:
    • routes
    • controllers
    • services
    • repositories
    • policies
  • Zod-based request validation
  • Typed request lifecycle (req.validated)
  • Centralized error handling
  • Structured logging with request IDs
  • OpenAPI / Swagger documentation

🏗️ Tech Stack

Layer Tech
Runtime Node.js
Language TypeScript
Framework Express 5
Database PostgreSQL
ORM Drizzle ORM
Validation Zod
Auth JWT (Access + Refresh)
Security Helmet, Rate Limiting
Logging Pino
Docs Swagger (OpenAPI 3)

📁 Project Structure

src/
├─ modules/
│  ├─ auth/
│  ├─ post/
│  ├─ comment/
│  ├─ post-like/
│  └─ tag/
│
├─ middlewares/
│  ├─ auth.middleware.ts
│  ├─ cors.middleware.ts
│  ├─ rate-limit.middleware.ts
│  ├─ security.middleware.ts
│  └─ error.middleware.ts
│
├─ db/
│  ├─ schema/
│  └─ index.ts
│
├─ docs/              # OpenAPI / Swagger
├─ utils/
├─ errors/
├─ @types/
├─ env.ts
├─ app.ts
└─ server.ts

🔐 Authentication Flow

1. Login / Signup

  • Returns access token (JWT)
  • Sets refresh token (HTTP-only cookie)

2. Authenticated Requests

  • Use Authorization: Bearer <access_token>

3. Token Refresh

  • Access token expires → /auth/refresh
  • Refresh token rotated automatically

4. Logout

  • All refresh tokens revoked
  • Cookie cleared

📚 Pagination Strategy (Cursor-Based)

Instead of offset, the API uses cursor pagination:

GET /posts?limit=10&cursor=2025-01-01T10:00:00Z

Response:

{
  "data": [...],
  "meta": {
    "nextCursor": "2025-01-01T09:12:30Z",
    "hasNextPage": true
  }
}

Why cursor pagination?

  • Stable ordering
  • No duplicate / skipped rows
  • Scales with large datasets

👍 Likes & Views (Correctly Done)

Likes

  • Unique per user per post
  • Stored in post_likes
  • Atomic counter updates via transactions
  • likedByMe included only when authenticated

Views

  • IP-based deduplication
  • Author views excluded
  • View count stored on post
  • Separate post_views table for analytics

🛡️ Security Measures

  • Rate limiting:
    • Auth routes (strict)
    • Public reads (soft)
    • Writes (moderate)
  • Helmet security headers
  • Strict CORS allowlist
  • No * origins with credentials
  • SQL injection safe via ORM
  • Passwords hashed with Argon2id
  • Timing-attack resistant auth checks

📖 API Documentation (Swagger)

Interactive OpenAPI docs available at:

/docs

Features:

  • JWT Bearer authentication
  • Request/response schemas
  • Pagination & auth documented
  • Clean separation from controllers

Docs are disabled in production for security.


⚙️ Environment Variables

NODE_ENV=development
PORT=6969
DATABASE_URL=postgresql://...
ACCESS_TOKEN_SECRET=...
REFRESH_TOKEN_SECRET=...

🧪 Scripts

pnpm dev # development
pnpm build # production build
pnpm start # start prod server

pnpm db:push
pnpm db:migrate
pnpm db:studio

🧠 Design Decisions

  • Policy-based authorization instead of hardcoded checks
  • Optional authentication for public routes
  • Single source of truth for roles
  • Explicit transactions for counters & relations
  • Zod at the boundary, not everywhere
  • Services stay framework-agnostic

👤 Author

Sameer Ali

Backend-focused full-stack developer Passionate about clean architecture, scalable APIs, and real-world systems.

⭐ Why This Project Matters

This is not a CRUD demo.

It demonstrates:

  • Real authentication flows
  • Scalable pagination
  • Proper authorization modeling
  • Production-grade security
  • Clean, maintainable backend architecture

If you’re reviewing this repo:
👉 this backend is ready to be extended, deployed, and scaled.

About

Production-grade REST API for a blogging platform, built with TypeScript, Express 5, and PostgreSQL — featuring JWT auth, RBAC, cursor pagination, and OpenAPI documentation.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published
Morty Proxy This is a proxified and sanitized view of the page, visit original site.