A URL shortener built with modern technologies. Features JWT authentication, real-time analytics, background job processing, and intelligent caching.
- URL Shortening: Convert long URLs into short, shareable links with base62 encoding
- User Authentication: JWT-based secure authentication with refresh tokens
- Analytics Tracking: Real-time visit counting and detailed analytics per URL
- Background Processing: Asynchronous job handling with RabbitMQ
- Intelligent Caching: Redis-based caching for top 100 most accessed links
- Rate Limiting: Redis-powered rate limiting to prevent abuse
- Swagger Documentation: Interactive API documentation
- Runtime: Node.js 20+
- Framework: Express.js
- Language: TypeScript
- Database: MongoDB with Mongoose ODM
- Cache: Redis
- Message Queue: RabbitMQ
- Authentication: JWT
- Testing: Jest + Supertest
- Documentation: Swagger/OpenAPI 3
- Containerization: Docker + Docker Compose
- CI/CD: GitHub Actions
- Architecture: Microservices with package-by-feature structure
graph TD
Client[Client/Browser]
API[Express API<br/>TypeScript]
MongoDB[(MongoDB)]
Redis[(Redis Cache)]
RabbitMQ[RabbitMQ<br/>Message Queue]
Worker[Background Worker<br/>Service]
Client -->|HTTP Requests| API
API -->|Store/Retrieve URLs| MongoDB
API -->|Cache Hot Links| Redis
API -->|Publish Jobs| RabbitMQ
RabbitMQ -->|Consume Jobs| Worker
Worker -->|Update Analytics| MongoDB
API -->|Rate Limiting| Redis
style API fill:#47A248
style MongoDB fill:#00684A
style Redis fill:#DC382D
style RabbitMQ fill:#FF6600
style Worker fill:#3178C6
url-shortener/
├── src/
│ ├── config/ # App configuration & connections
│ ├── libs/ # Shared utilities and helpers
│ ├── common/ # Common resources (middlewares, errors, utils)
│ ├── modules/ # Feature-based modules
│ │ ├── core/ # Health checks & monitoring
│ │ ├── auth/ # Authentication logic
│ │ ├── user/ # User management
│ │ ├── url/ # URL shortening & redirect
│ │ └── analytics/ # Analytics tracking
│ ├── app.ts # Express app setup
│ └── server.ts # Application entry point
├── tests/ # Global test setup
├── .github/workflows/ # CI/CD pipelines
├── docker-compose.yml # Production container setup
├── docker-compose.dev.yml # Development container setup
├── Dockerfile # Production image
├── Dockerfile.dev # Development image
└── package.json # Dependencies & scripts
- Node.js 20+
- Docker & Docker Compose
- MongoDB (or use Docker)
- Redis (or use Docker)
- RabbitMQ (or use Docker)
- Clone the repository:
git clone git@github.com:Veras-D/url-shortener.git
cd url-shortener- Install dependencies:
npm install- Configure environment variables:
cp .env.example .envEdit .env with your configuration:
NODE_ENV=development
PORT=3000
MONGODB_URI=mongodb://localhost:27017/url-shortener
REDIS_URL=redis://localhost:6379
RABBITMQ_URL=amqp://localhost:5672
JWT_SECRET=your-jwt-secret
JWT_REFRESH_SECRET=your-refresh-secret
JWT_EXPIRES_IN=15m
JWT_REFRESH_EXPIRES_IN=7d
FRONTEND_URL=http://localhost:5173- Start with Docker Compose:
npm run compose:dev- Access the application:
- Backend API:
http://localhost:3000 - API Documentation:
http://localhost:3000/api-docs - RabbitMQ Management:
http://localhost:15672(guest/guest)
- Backend API:
Start development server:
npm run devGET /health- Service health status
POST /api/shorten- Create short URLGET /:shortCode- Redirect to original URLGET /api/urls- Get user's URLsDELETE /api/urls/:shortCode- Delete short URL
GET /api/stats/:shortCode- Get URL statistics
POST /api/auth/register- Register new userPOST /api/auth/login- User loginPOST /api/auth/refresh- Refresh access tokenPOST /api/auth/logout- User logout
npm testnpm run test:watchnpm run test:coveragenpm run compose:devnpm run compose:prodnpm run debug{
email: string;
password: string;
createdAt: Date;
}{
originalUrl: string;
shortCode: string;
userId: ObjectId;
visitCount: number;
createdAt: Date;
}{
shortCode: string;
timestamp: Date;
userAgent: string;
ip: string;
}| Script | Description |
|---|---|
dev |
Start development server |
build |
Build TypeScript to JavaScript |
start |
Start production server |
test |
Run all tests |
lint |
Run ESLint |
lint:fix |
Run ESLint with auto-fix |
prettier |
Format code with Prettier |
compose:dev |
Start development environment |
compose:prod |
Start production environment |
debug |
Debug container shell access |
- JWT authentication with refresh tokens
- Password hashing with bcrypt
- Rate limiting per IP address
- CORS protection
- Security headers with Helmet
- Input validation
- Redis-based session management
Contributions are welcome! Follow these steps to contribute to the project:
- Browse existing issues or create a new one
- Comment on the issue to let others know you're working on it
- Wait for approval from maintainers before starting work
git clone git@github.com:YOUR_USERNAME/url-shortener.git
cd url-shortenernpm install
cp .env.example .envEdit .env with appropriate values, then start services:
npm run compose:devgit checkout -b feature/issue-number-short-descriptionBranch naming convention:
feature/123-add-custom-domainsfor new featuresfix/456-redirect-errorfor bug fixesdocs/789-update-readmefor documentationrefactor/101-improve-cachefor refactoring
- Write clean, maintainable code
- Follow the existing code structure and style
- Add tests for new features
- Update documentation if needed
Use Conventional Commits format:
git commit -m "feat: add custom domain support"
git commit -m "fix: resolve redirect loop issue"
git commit -m "docs: update API documentation"
git commit -m "test: add unit tests for url service"Commit types:
feat: New featurefix: Bug fixdocs: Documentation changestest: Adding or updating testsrefactor: Code refactoringstyle: Code style changes (formatting, etc.)chore: Maintenance tasks
Ensure all tests pass and code follows style guidelines:
npm run lint
npm run lint:fix
npm testAll checks must pass before submitting a PR.
git push origin feature/issue-number-short-descriptionThen:
- Go to the repository on GitHub
- Click "New Pull Request"
- Select your branch
- Fill in the PR template with:
- Description of changes
- Related issue number
- Screenshots (if applicable)
- Wait for review from maintainers
- Maintainers will review your PR
- Address any requested changes
- Once approved, your PR will be merged
Thank you for contributing!
© 2025 VERAS. All rights reserved.