PLANNING.md
Rama main · réplica de lectura del repositorio original.
# Linkas — URL Shortener API
## Overview
A simple, fast URL shortener API built with Go + Gin + PostgreSQL.
## Tech Stack
- **Language:** Go 1.26+
- **Framework:** Gin
- **Database:** PostgreSQL
- **ORM:** sqlx (lightweight, close to raw SQL)
- **Migration:** Custom migration runner (`cmd/migrate/main.go`)
- **Testing:** Go stdlib testing
## Features
- [x] POST /api/shorten — Create short URL
- [x] GET /:slug — Redirect to original URL
- [x] GET /api/stats/:slug — Get click analytics
- [x] DELETE /api/:slug — Delete short URL
- [x] Rate limiting per IP
- [x] Custom slug support
- [x] URL validation
- [x] Click tracking (user-agent, referrer, IP)
## Database Schema
```sql
CREATE TABLE urls (
id SERIAL PRIMARY KEY,
slug VARCHAR(10) UNIQUE NOT NULL,
original_url TEXT NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP,
click_count INTEGER DEFAULT 0
);
CREATE TABLE clicks (
id SERIAL PRIMARY KEY,
url_id INTEGER REFERENCES urls(id) ON DELETE CASCADE,
ip_address VARCHAR(45),
user_agent TEXT,
referrer TEXT,
clicked_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_urls_slug ON urls(slug);
CREATE INDEX idx_clicks_url_id ON clicks(url_id);
```
## API Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | `/api/shorten` | Create short URL |
| GET | `/:slug` | Redirect to original URL |
| GET | `/api/stats/:slug` | Get click stats |
| DELETE | `/api/:slug` | Delete short URL |
| GET | `/api/health` | Health check |
## Project Structure
```
linkas/
├── main.go # Entry point, router setup
├── go.mod
├── go.sum
├── cmd/
│ └── migrate/ # Migration runner
│ └── main.go
├── internal/
│ ├── handler/ # HTTP handlers
│ │ └── url.go
│ ├── model/ # Data models
│ │ └── url.go
│ ├── repository/ # Database queries
│ │ └── url_repo.go
│ ├── service/ # Business logic
│ │ └── url_service.go
│ └── middleware/ # Rate limiting, etc.
│ └── rate_limit.go
├── migrations/ # SQL migrations
│ └── 001_init.sql
├── docker-compose.yml
├── Dockerfile
├── .env.example
└── README.md
```
## Slug Generation
- Use base62 encoding (a-z, A-Z, 0-9)
- Default length: 6 characters
- Collision check: regenerate if slug exists
## Rate Limiting
- 30 requests per minute per IP
- Return 429 Too Many Requests when exceeded
## Environment Variables
```env
PORT=8080
DATABASE_URL=postgres://user:pass@localhost:5432/linkas?sslmode=disable
BASE_URL=http://localhost:8080
```
## Quick Commands
```bash
# Copy env file
cp .env.example .env
# Run migrations
go run cmd/migrate/main.go up
# Check migration version
go run cmd/migrate/main.go version
# Rollback migration
go run cmd/migrate/main.go down
# Start API
go run main.go
```
## Phase 1 (MVP)
- [ ] Project setup (go mod, gin, docker)
- [ ] Database connection and migrations
- [ ] URL CRUD (create, read, delete)
- [ ] Redirect with click tracking
- [ ] Basic stats endpoint
## Phase 2 (Enhancement)
- [ ] Rate limiting middleware
- [ ] URL expiration
- [ ] Input validation
- [ ] Error handling
- [ ] Unit tests
## Phase 3 (Polish)
- [ ] Docker optimization
- [ ] README with examples
- [ ] CI/CD setup
- [ ] Performance testing