Skip to content

mustaphalimar/limus-shortener

Repository files navigation

Limus Shortener

Note: This README was generated with the assistance of AI to provide comprehensive project documentation.

A modern, full-featured URL shortener built with Go, featuring server-side rendering with Templ templates, HTMX for dynamic interactions, and styled with Tailwind CSS. The application provides user authentication, link management, visit tracking, and a clean, responsive interface.

Features

  • 🔗 URL Shortening: Generate short, unique codes for long URLs using Base62 encoding with UUID v7
  • 👤 User Authentication: Secure registration and login with JWT-based authentication
  • 📊 Visit Tracking: Track click analytics and IP addresses for each shortened link
  • 🎨 Modern UI: Server-side rendered templates with HTMX for dynamic updates
  • Redis Caching: Fast link resolution with Redis caching layer
  • 🐘 PostgreSQL Database: Robust data persistence with proper migrations
  • 🔐 Security: Password hashing with bcrypt, JWT tokens, and secure middleware
  • 🚀 Production Ready: Docker support with health checks and graceful shutdown

Tech Stack

Backend

  • Go 1.25+: Core application language
  • Chi Router: Lightweight and fast HTTP router
  • PostgreSQL: Primary database with pgx driver
  • Redis: Caching and performance optimization
  • Templ: Type-safe Go templating engine
  • Goose: Database migration tool

Frontend

  • HTMX: Dynamic HTML interactions without JavaScript
  • Tailwind CSS: Utility-first CSS framework
  • Alpine.js: Minimal JavaScript for UI interactions

Infrastructure

  • Docker & Docker Compose: Containerization and orchestration
  • Railway: Deployment platform (configured)

Project Structure

limus-shortener/
├── cmd/
│   └── api/
│       └── main.go                 # Application entry point
├── internal/
│   ├── config/                     # Configuration management
│   ├── database/                   # Database connection and migrations
│   │   └── migrations/             # SQL migration files
│   ├── domain/                     # Domain models and interfaces
│   │   ├── link.go
│   │   └── user.go
│   ├── handler/                    # HTTP request handlers
│   │   ├── auth_handler.go
│   │   └── link_handler.go
│   ├── logger/                     # Structured logging
│   ├── middleware/                 # HTTP middleware (auth, logging, etc.)
│   ├── redis/                      # Redis caching layer
│   ├── repository/                 # Data access layer
│   │   ├── link.go
│   │   └── user.go
│   ├── router/                     # Route definitions
│   ├── server/                     # HTTP server configuration
│   ├── service/                    # Business logic layer
│   │   ├── link_service.go
│   │   └── user_service.go
│   ├── utils/                      # Utility functions
│   │   ├── base62.go              # URL shortening algorithm
│   │   ├── jwt.go                 # JWT token management
│   │   ├── password.go            # Password hashing
│   │   └── url.go                 # URL validation
│   └── validator/                  # Request validation
├── views/
│   ├── components/                 # Reusable Templ components
│   ├── layouts/                    # Page layouts
│   └── pages/                      # Page templates
├── static/
│   ├── css/                        # Tailwind CSS files
│   └── images/                     # Static images
├── tests/
│   ├── helpers/                    # Test utilities
│   └── mocks/                      # Mock implementations
├── docker-compose.yml              # Local development setup
├── Dockerfile                      # Production container
├── Makefile                        # Build and development commands
└── go.mod                          # Go dependencies

Prerequisites

  • Go: 1.25 or higher
  • PostgreSQL: 14+ (or use Docker Compose)
  • Redis: 7+ (or use Docker Compose)
  • Node.js: 20+ (for Tailwind CSS compilation)
  • Docker & Docker Compose: For containerized development (optional)

Installation

1. Clone the Repository

git clone https://github.com/mustaphalimar/limus-shortener.git
cd limus-shortener

2. Install Dependencies

# Install Go dependencies
go mod download

# Install Node.js dependencies for Tailwind CSS
npm install

# Install Templ CLI
go install github.com/a-h/templ/cmd/templ@latest

# Install Goose for migrations
go install github.com/pressly/goose/v3/cmd/goose@latest

3. Environment Configuration

Create a .env file in the root directory:

# Server Configuration
PORT=8080
HOST=0.0.0.0
APP_ENV=development
BASE_URL=http://localhost:8080

# Database Configuration
DATABASE_URL=postgresql://postgres:password@localhost:5432/limus_shortener?sslmode=disable
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=password
DB_NAME=limus_shortener
DB_SSL_MODE=disable
DB_MAX_OPEN_CONNS=25
DB_IDLE_OPEN_CONNS=25

# Redis Configuration
REDIS_ADDRESS=localhost:6379
REDIS_USERNAME=
REDIS_PASSWORD=
REDIS_DB=0

# JWT Configuration
JWT_SECRET=your-secret-key-here-change-in-production
JWT_EXPIRATION_HOURS=24
JWT_REFRESH_HOURS=168
JWT_ISSUER=limus-shortener

# Logger Configuration
LOG_LEVEL=info
LOG_FORMAT=text

4. Database Setup

Using Docker Compose (Recommended)

# Start PostgreSQL and Redis
docker-compose up -d postgres redis

# Run migrations
make migrate-up

Manual Setup

# Create database
createdb limus_shortener

# Run migrations
goose -dir internal/database/migrations postgres "your-connection-string" up

Usage

Development Mode

Start the development server with hot reload for Templ, CSS, and Go files:

make dev

This will start the server at http://localhost:8080

Production Build

# Generate Templ templates
make templ

# Build CSS
npm run build:css

# Build binary
make build

# Run the binary
./bin/limus_shortener

Using Docker

# Build and run all services
docker-compose up --build

# Run in detached mode
docker-compose up -d

# View logs
docker-compose logs -f app

# Stop services
docker-compose down

Available Make Commands

make help           # Display all available commands
make run            # Run the application
make dev            # Start development mode with hot reload
make build          # Build the application binary
make templ          # Generate Templ templates
make watch-templ    # Watch and regenerate Templ files
make watch-css      # Watch and rebuild CSS
make test           # Run tests
make clean          # Clean build artifacts
make migrate-up     # Run database migrations
make migrate-down   # Rollback database migrations
make migrate-status # Check migration status

API Endpoints

Authentication

  • GET /register - Registration page
  • POST /register - Create new user account
  • GET /login - Login page
  • POST /login - Authenticate user
  • POST /logout - Logout user

Link Management

  • GET / - Home page (authenticated users)
  • POST /api/links - Generate shortened link
  • GET /:shortLink - Redirect to original URL
  • GET /my-links - View user's links
  • DELETE /api/links/:id - Delete a link

Architecture

Layered Architecture

The application follows a clean architecture pattern with clear separation of concerns:

  1. Handler Layer: HTTP request/response handling and input validation
  2. Service Layer: Business logic and orchestration
  3. Repository Layer: Data access and persistence
  4. Domain Layer: Core business entities and interfaces

URL Shortening Algorithm

The application uses a Base62 encoding scheme with UUID v7 (time-based UUIDs):

  1. Generate a UUID v7 timestamp-based identifier
  2. Convert UUID bytes to a big integer
  3. Encode the integer using Base62 (0-9, A-Z, a-z)
  4. Truncate to 10 characters for a short, unique code

This approach ensures:

  • Collision resistance through UUID v7
  • URL-safe characters only
  • Time-ordered generation for better database indexing
  • Approximately 839 quadrillion possible combinations

Caching Strategy

Redis is used as a caching layer for link resolution:

  • Cache hits return immediately without database query
  • Cache misses fetch from PostgreSQL and populate cache
  • TTL-based expiration for automatic cache management

Testing

Note: Testing suite is still not implemented. Planned testing coverage includes:

  • Unit tests for services and utilities
  • Integration tests for repositories
  • End-to-end API tests
  • Mock implementations for external dependencies

Database Schema

Users Table

  • User authentication and profile information
  • Bcrypt password hashing
  • Timestamps for created_at and updated_at

Links Table

  • Original URL and shortened code
  • Foreign key to users table
  • Visit counter
  • Indexed on short_link and user_id

Link Visits Table

  • Visit tracking with timestamps
  • IP address recording
  • Foreign key to links table

Security Considerations

  • Password Security: Passwords hashed with bcrypt (cost factor 10)
  • JWT Tokens: Secure token-based authentication with expiration
  • Input Validation: URL validation and sanitization
  • SQL Injection: Prepared statements via pgx driver
  • HTTPS: Recommended for production deployments
  • Environment Variables: Sensitive data stored in environment variables

Deployment

Railway Deployment

The project includes a railway.toml configuration for easy deployment:

# Install Railway CLI
npm i -g @railway/cli

# Login to Railway
railway login

# Deploy
railway up

Manual Deployment

  1. Build the Docker image
  2. Set environment variables
  3. Run database migrations
  4. Start the container with proper health checks
  5. Configure reverse proxy (Nginx/Caddy) for HTTPS

Performance Optimization

  • Connection Pooling: Configured for PostgreSQL (max 25 connections)
  • Redis Caching: Sub-millisecond link resolution
  • Compression: HTTP response compression (level 5)
  • Static Assets: Minified CSS in production
  • Database Indexing: Optimized queries with proper indexes

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is open source and available under the MIT License.

Acknowledgments

Author

Mustapha Limar

Support

For issues, questions, or contributions, please open an issue on the GitHub repository.

About

A simple URL shortener built with Go, Templ, HTMX, Tailwincss, Alpine.Js

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors