A modern URL shortener built with Go, featuring a clean UI with HTMX for dynamic interactions.
This app was vibe-coded end-to-end — my human trusted me.
- URL Shortening: Create short, memorable aliases for long URLs
- Inline Editing: Edit URLs and aliases directly in the list with HTMX
- Real-time Search: Search through links with debounced input
- Statistics: Track clicks and view usage statistics
- Hot Links: View trending links over different time periods
- Dark Mode: Built-in dark mode support
Get to your short URLs even faster with the quickr-jump browser extension — Faster than Quickr!
- What it is: A Firefox & Chrome extension to use Quickr faster
- Source: AurelienS/quickr-jump
- Backend: Go with Gin framework
- Database: SQLite with GORM
- Frontend: HTMX + Tailwind CSS
- Deployment: Single binary with embedded assets
# Build and start the application
docker compose up -d
# View logs
docker compose logs -f
# Stop the application
docker compose downThe application will be available at http://localhost:8080
- Build the binary:
go build -o quickr- Run the application:
./quickrquickr/
├── data/ # Database directory (created on first run)
├── handlers/ # HTTP handlers
├── models/ # Database models
├── static/ # Static assets
│ └── js/ # JavaScript files
├── templates/ # HTML templates
├── main.go # Application entry point
└── resources.go # Embedded resources
The application uses Go's embed feature to include all necessary assets in a single binary:
- Templates: All HTML templates are embedded
- Static Files: JavaScript and other static assets are embedded
- Database: SQLite database is stored externally in a data directory
- Resources are defined in
resources.go:
//go:embed templates/*.html
var templateFS embed.FS
//go:embed static/js/*.js
var staticFS embed.FS- The application loads these resources at runtime:
- Templates are parsed from
templateFS - Static files are served from
staticFS - Database is stored in
./data/quickr.db
- Multi-stage build for minimal image size
- Non-root user for security
- Volume for database persistence
- Automatic restart on failure
The SQLite database is stored in a Docker volume for persistence:
# Backup database
docker compose exec quickr sqlite3 /app/data/quickr.db ".backup '/app/data/backup.db'"
# Restore database
docker compose exec quickr sqlite3 /app/data/quickr.db ".restore '/app/data/backup.db'"None required. The application uses sensible defaults:
- Port: 8080
- Database: /app/data/quickr.db
- Go 1.21 or higher
- SQLite3
- Clone the repository:
git clone <repository-url>
cd quickr- Install dependencies:
go mod download- Run the application:
go run main.goFor production deployment:
# Build with embedded resources
go build -o quickr
# Test the build
./build.shGET /: Homepage with link managementGET /hot: Trending links viewGET /stats: Usage statisticsGET /go/:alias: Link redirection
API endpoints:
GET /api/links: List all linksPOST /api/links: Create new linkPUT /api/links/:id: Update linkDELETE /api/links/:id: Delete linkGET /api/search: Search links
- SQLite database is stored in a dedicated directory
- Docker container runs as non-root user
- No sensitive environment variables required
- Input validation for URLs and aliases
MIT License