Source: Jolli-sample-repos/url-shortener Last Updated: 4/8/2026
URL Shortener - Project Specification
Project Overview
Domain: Utilities / URL Management Language: TypeScript Complexity: Simple (5-10 files) Type: RESTful API with OpenAPI/Swagger documentation
A URL shortening service that creates short, memorable links for long URLs, tracks click analytics, and provides redirect functionality.
Feature Requirements
1. URL Shortening
- Create short URLs from long URLs
- Generate random short codes (6-8 characters)
- Optional custom short codes (if available)
- Validate URL format before creating
- Prevent duplicate long URLs (return existing short code)
2. URL Redirection
- Redirect short URLs to original long URLs
- Return 404 for non-existent short codes
- Track redirect count on each access
3. URL Management
- Retrieve URL details by short code
- List all URLs (paginated)
- Delete URLs by short code
- Update long URL for existing short code
4. Analytics
- Track total clicks per short URL
- Track last accessed timestamp
- Get top URLs by click count
- Global statistics (total URLs, total clicks)
5. Validation & Expiry
- URL format validation
- Optional expiration date for short URLs
- Return 410 Gone for expired URLs
API Endpoints Specification
Base URL: /api/v1
| Method | Endpoint | Description | Request Body | Response |
|---|---|---|---|---|
| POST | /urls | Create a short URL | { longUrl, customCode?, expiresAt? } | 201: ShortUrl, 400: Invalid URL/Code Taken |
| GET | /urls/:shortCode | Get URL details | None | 200: ShortUrl, 404: Not Found |
| GET | /urls | List all URLs | Query: page, limit | 200: { urls: ShortUrl[], total, page, limit } |
| PUT | /urls/:shortCode | Update long URL | { longUrl } | 200: ShortUrl, 404: Not Found |
| DELETE | /urls/:shortCode | Delete short URL | None | 204: No Content, 404: Not Found |
| GET | /r/:shortCode | Redirect to long URL | None | 302: Redirect, 404: Not Found, 410: Expired |
| GET | /stats | Get global statistics | None | 200: GlobalStats |
| GET | /stats/top | Get top URLs by clicks | Query: limit (default: 10) | 200: ShortUrl[] |
Data Models
interface ShortUrl {
shortCode: string;
longUrl: string;
createdAt: string;
expiresAt?: string;
clicks: number;
lastAccessedAt?: string;
}
interface CreateUrlRequest {
longUrl: string;
customCode?: string; // 4-20 alphanumeric characters
expiresAt?: string; // ISO 8601 format
}
interface UpdateUrlRequest {
longUrl: string;
}
interface GlobalStats {
totalUrls: number;
totalClicks: number;
activeUrls: number;
expiredUrls: number;
}
interface PaginatedResponse {
urls: ShortUrl[];
total: number;
page: number;
limit: number;
hasMore: boolean;
}Folder Structure
url-shortener/
├── src/
│ ├── index.ts # Entry point & Express setup
│ ├── routes.ts # All route definitions
│ ├── models.ts # TypeScript interfaces & types
│ ├── storage.ts # In-memory data storage
│ ├── validator.ts # URL and code validation
│ ├── generator.ts # Short code generation logic
│ └── swagger.ts # OpenAPI/Swagger configuration
├── package.json
├── tsconfig.json
├── .gitignore
├── README.md
└── PROJECT_SPEC.mdTech Stack
Core Dependencies
- Runtime: Node.js 18+
- Framework: Express.js 4.x
- Language: TypeScript 5.x
- Validation: zod or joi
- Documentation: swagger-ui-express, swagger-jsdoc
- Utilities: nanoid (for short code generation)
Dev Dependencies
- ts-node
- @types/node
- @types/express
- nodemon
Database Schema
Note: This simple version uses in-memory storage (Map). No actual database required.
// In-memory storage structure
const urls: Map<string, ShortUrl> = new Map();
const longUrlIndex: Map<string, string> = new Map(); // longUrl -> shortCodeShort Code Generation Logic
- Use
nanoidor custom base62 encoding - Default length: 6-8 characters
- Character set: [a-zA-Z0-9]
- Collision detection: regenerate if code exists
- Custom codes: validate format and availability
Setup Instructions Template
Prerequisites
- Node.js 18 or higher
- npm or yarn
Installation
npm installDevelopment
npm run devBuild
npm run buildRun Production
npm startConfiguration
Environment variables:
PORT=3000
BASE_URL=http://localhost:3000
SHORT_CODE_LENGTH=6API Documentation
Access Swagger UI at: http://localhost:3000/api-docs
OpenAPI Documentation Requirements
- All endpoints must be documented with OpenAPI 3.0 specification
- Include request/response schemas
- Include example requests and responses
- Document query parameters for pagination
- Include error response schemas (400, 404, 410, 500)
- Document redirect behavior for
/r/:shortCodeendpoint
Success Criteria
- All 8 endpoints are functional and return correct responses
- Short code generation works without collisions
- Custom short codes can be created if available
- Redirects work correctly and increment click count
- Expired URLs return 410 status
- Analytics accurately track clicks and timestamps
- Pagination works correctly for URL listing
- OpenAPI/Swagger documentation is complete and accessible
- Code is well-structured and follows TypeScript best practices
- README includes clear setup and usage instructions