Skip to content

Repository files navigation

cutter

✂️ Cutter is a tiny URL shortener built with Go, HTMX, and SQLite.

The goal is to showcase how I approach end-to-end backend development: clean layering, explicit naming conventions and development tooling.

Architecture at a glance

  • Domain (internal/domain/link) – contains the bussiness logic.
  • Application (internal/app) – orchestrates use cases through handlers that consume DTO commands/results. Policies are injected here before touching repositories.
  • Interface (internal/interface/http) – exposes an HTMX-powered web UI and REST endpoints built on a small router (pkg/amigo) plus Tailwind/templ templates.
  • Infrastructure (internal/infra) – SQLite persistence generated via sqlc, logger setup, and dependency wiring.
  • Packaging – multi-stage Dockerfile producing a distroless image; docker compose (with .env support) starts the API plus any backing services.

Technical highlights

  • Go 1.25, HTMX UI components powered by a-h/templ, and tailwindcss build pipeline.
  • SQLite persistence via sqlc.
  • Migrations done with goose.
  • Embedded static assets (static/) served through go:embed.
  • Makefile-driven workflow (generate templates, build CSS, run server, docker compose up).
  • Naming convention (Command/Handler/Result) enforced across handlers.

Development setup

Prerequisites

  • Go >= 1.25
  • Develop environment is provided through flake.nix + .envrc using direnv.
  • Go tool dependencies (templ, goose, sqlc) are declared in go.mod.

Useful commands

make init        # Generate templates, css, sqlc code
make serve       # Run the app with all assets up to date
make watch       # Auto-rebuild on file changes
make build       # Compile the Go binary into ./bin/cutter
make up          # docker compose up --build with project name cutter

Naming Guidelines

  • Commands (CreateLinkCommand, VisitLinkCommand, …) are DTOs that capture the input for a use case.
  • Handlers (CreateLinkHandler, VisitLinkHandler, …) execute the use case via a Handle method and orchestrate repositories, policies and other services.
  • Results (CreateLinkResult, …) hold the data returned by handlers.
  • Policies (e.g. link.CreatePolicy) capture domain rules such as URL validation or expiration defaults so that the domain stays consistent and reusable.

Other

  • pkg/amigo – a custom HTTP toolkit I’m evolving to offer a “friendly API” (hence the name “amigo”) developer experience, inspired by frameworks like FastAPI. It currently powers routing, middleware, and static delivery and will keep growing.

About

🔪 A lightweight, fast URL shortener built with Go, HTMX and SQLite.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages