Guide for developing and maintaining a minimalist Go link shortener with htmx, SQLite, and hybrid auth
You are working with a minimalist link shortener service for Avanti Fellows (~200 internal users). The service provides URL shortening with analytics, featuring a **hybrid authentication model**: public dashboard/redirects and Bearer token protected API endpoints.
```
internal/
├── handlers/handlers.go # HTTP handlers, template rendering, async click tracking
├── services/shortener.go # URL validation, short code generation
├── database/database.go # SQLite setup, migrations, connection pooling
├── models/link.go # LinkMapping and ClickAnalytics structs
├── middleware/auth.go # Bearer token authentication
└── logger/logger.go # Structured logging
cmd/
├── server/main.go # Entry point, Chi router setup
└── import/main.go # Data import utility (if exists)
templates/ # Go html/templates with htmx
├── base.html
├── dashboard.html
├── analytics-table.html # htmx partial
└── success-message.html
```
1. **Environment Setup**:
```bash
cp .env.example .env.local
# Edit .env.local: AUTH_TOKEN=<uuidgen output>
```
2. **Install Dependencies & Run**:
```bash
go mod tidy
go run cmd/server/main.go
```
3. **Required .env.local Variables**:
```bash
AUTH_TOKEN=your-uuid-token-here
DATABASE_PATH=./link_shortener.db
PORT=8080
BASE_URL=http://localhost:8080
DEBUG=true
LOG_LEVEL=INFO
```
**API Test Suite** (requires running server):
```bash
./test_api.sh # Comprehensive tests for all endpoints
```
**Manual API Testing**:
```bash
export AUTH_TOKEN="your-uuid-token"
curl -X POST http://localhost:8080/shorten \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H "Accept: application/json" \
-d "original_url=https://example.com&created_by=test"
```
**Go Tests** (when test files exist):
```bash
go test ./...
go test -race ./...
go test -bench=. ./...
```
```bash
go build -o link-shortener cmd/server/main.go
CGO_ENABLED=0 go build -ldflags="-s -w" -o link-shortener cmd/server/main.go
./deploy.sh
```
**Tables**:
**Go Models**:
```go
// Public routes
r.Get("/health", h.Health)
r.Get("/", h.Dashboard)
r.Get("/{code}", h.RedirectURL)
// Authenticated API routes
r.Route("/api", func(r chi.Router) {
r.Use(authmiddleware.AuthMiddleware)
r.Get("/links", h.Analytics)
r.Post("/links", h.CreateShortURL)
r.Get("/links/{code}", h.GetLink)
r.Put("/links/{code}", h.UpdateLink)
r.Delete("/links/{code}", h.DeleteLink)
})
// Legacy routes (backward compatibility, protected)
r.Post("/shorten", h.CreateShortURL)
r.Get("/analytics", h.Analytics)
```
```go
// Background channel prevents blocking redirects
clickQueue := make(chan ClickEvent, 1000)
go h.processClickQueue() // Background goroutine processes clicks
```
1. Add route in `cmd/server/main.go`
2. Implement handler in `internal/handlers/handlers.go`
3. Update models in `internal/models/link.go` if needed
4. Add tests to `test_api.sh`
5. Update templates if UI changes required
1. Update schema in `internal/database/database.go`
2. Add new models to `internal/models/link.go`
3. Test migrations with existing data
4. Update handlers and services accordingly
1. Edit `templates/*.html` files
2. Test htmx functionality locally
3. Ensure responsive design with Tailwind classes
4. Verify desktop and mobile layouts
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/link-shortener-service-development/raw