Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 

Repository files navigation

SnapURL — URL Shortener Microservice

A full-stack URL shortener with authentication, analytics, QR codes, admin panel, Redis caching, BullMQ background jobs, and more.


Tech Stack

Backend: Node.js, Express, MongoDB (Mongoose), Redis (ioredis), BullMQ, nanoid, JWT, bcryptjs, QRCode
Frontend: React 18, Vite, Tailwind CSS, Recharts, React Hook Form, React Router v6, Axios


Project Structure

urlshortener/
├── backend/
│   ├── src/
│   │   ├── config/        # db.js, redis.js
│   │   ├── controllers/   # authController, urlController, adminController
│   │   ├── middleware/    # auth.js, rateLimiter.js, errorHandler.js
│   │   ├── models/        # User.js, Url.js
│   │   ├── routes/        # auth.js, urls.js, admin.js, redirect.js
│   │   ├── services/      # authService, urlService, adminService
│   │   ├── jobs/          # clickQueue.js (BullMQ)
│   │   ├── utils/         # jwt.js, validators.js
│   │   ├── app.js
│   │   └── server.js
│   ├── .env.example
│   └── package.json
└── frontend/
    ├── src/
    │   ├── components/    # layout, dashboard, admin, ui
    │   ├── context/       # AuthContext.jsx
    │   ├── pages/         # Home, Login, Register, Dashboard, Analytics, Admin
    │   ├── services/      # api.js (axios + token refresh)
    │   └── main.jsx
    ├── index.html
    └── package.json

Quick Start

1. Configure Backend

cd backend
cp .env.example .env
# Edit .env with your MongoDB URI, Redis URL, and JWT secrets
npm install
npm run dev

2. Start Frontend

cd frontend
npm install
npm run dev

Frontend runs on http://localhost:3000, backend on http://localhost:5000.


Environment Variables (backend/.env)

Variable Description Default
PORT Server port 5000
MONGODB_URI MongoDB connection string
REDIS_URL Redis connection string redis://localhost:6379
BASE_URL Public URL of backend http://localhost:5000
JWT_ACCESS_SECRET Secret for access tokens
JWT_REFRESH_SECRET Secret for refresh tokens
JWT_ACCESS_EXPIRES_IN Access token TTL 15m
JWT_REFRESH_EXPIRES_IN Refresh token TTL 7d
RATE_LIMIT_MAX_AUTH Max auth attempts per 15 min 10
RATE_LIMIT_MAX_SHORTEN Max shorten requests per min 20
CLIENT_URL Frontend origin for CORS http://localhost:3000

API Reference

Auth

Method Endpoint Description
POST /api/auth/register Register user
POST /api/auth/login Login, returns JWT pair
POST /api/auth/refresh Refresh access token
POST /api/auth/logout Invalidate refresh token
GET /api/auth/me Get current user

URLs

Method Endpoint Description
POST /api/urls Create short URL
GET /api/urls/my Get current user's links
GET /api/urls/:code/analytics Get analytics
GET /api/urls/:code/qr Get QR code
PUT /api/urls/:code Update link
DELETE /api/urls/:code Delete link

Redirect

Method Endpoint Description
GET /:code Redirect to original URL

For password-protected links, send the password in the x-link-password header or ?p= query param.

Admin (requires admin role)

Method Endpoint Description
GET /api/admin/stats System statistics
GET /api/admin/links All links (paginated)
DELETE /api/admin/links/:code Delete any link
GET /api/admin/users All users (paginated)
PATCH /api/admin/users/:id/promote Promote user to admin

Health

Method Endpoint Description
GET /health MongoDB + Redis status

Features

  • ✅ User registration & login with JWT access + refresh token rotation
  • ✅ Password-protected short links (bcrypt)
  • ✅ Custom aliases (4–20 chars)
  • ✅ Link expiry with MongoDB TTL index
  • ✅ Redis read-through caching (falls back to DB on error)
  • ✅ BullMQ background queue for non-blocking click tracking
  • ✅ Analytics: clicks by date & referrer with Recharts line chart
  • ✅ QR code generation (PNG data URL)
  • ✅ Admin panel: system stats, link moderation, user management
  • ✅ Per-user + global rate limiting (Redis-backed, distributed)
  • ✅ Graceful shutdown (closes DB, Redis, BullMQ workers)
  • ✅ Health check endpoint
  • ✅ Morgan HTTP logging
  • ✅ Structured JSON error responses
  • ✅ Automatic 401 token refresh in frontend (Axios interceptor)

Making a User Admin

Use MongoDB shell or Compass:

db.users.updateOne({ email: "you@example.com" }, { $set: { isAdmin: true } })

Or promote via the Admin Panel once you have one admin.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages