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.
- 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
- 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
likedByMesupport for authenticated users
- Nested comments (replies)
- Cursor pagination
- Ownership & admin moderation policies
- Normalized tag system
- Many-to-many post ↔ tags
- Popular tags endpoint
- Safe deduplication & normalization
- 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
| 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) |
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- Returns access token (JWT)
- Sets refresh token (HTTP-only cookie)
- Use
Authorization: Bearer <access_token>
- Access token expires →
/auth/refresh - Refresh token rotated automatically
- All refresh tokens revoked
- Cookie cleared
Instead of offset, the API uses cursor pagination:
GET /posts?limit=10&cursor=2025-01-01T10:00:00ZResponse:
{
"data": [...],
"meta": {
"nextCursor": "2025-01-01T09:12:30Z",
"hasNextPage": true
}
}- Stable ordering
- No duplicate / skipped rows
- Scales with large datasets
- Unique per user per post
- Stored in
post_likes - Atomic counter updates via transactions
likedByMeincluded only when authenticated
- IP-based deduplication
- Author views excluded
- View count stored on post
- Separate
post_viewstable for analytics
- 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
Interactive OpenAPI docs available at:
/docsFeatures:
- JWT Bearer authentication
- Request/response schemas
- Pagination & auth documented
- Clean separation from controllers
Docs are disabled in production for security.
NODE_ENV=development
PORT=6969
DATABASE_URL=postgresql://...
ACCESS_TOKEN_SECRET=...
REFRESH_TOKEN_SECRET=...
pnpm dev # development
pnpm build # production build
pnpm start # start prod server
pnpm db:push
pnpm db:migrate
pnpm db:studio- 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
Backend-focused full-stack developer Passionate about clean architecture, scalable APIs, and real-world systems.
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.