A web forum built in Go, backed by SQLite. Registered users can create posts tagged with one or more categories, comment on posts, and like/dislike posts and comments; visitors can read everything but must register to participate. Posts can be filtered by category, by the logged-in user's own posts, or by posts the logged-in user has liked.
The category set is anime-themed, grouped into four kinds — demographic (Shonen, Shoujo, Seinen, Josei), genre (Action, Romance, Isekai, Mecha, Slice of Life, Fantasy, Horror, Comedy, Sports), theme (School, Music, Military, Supernatural, Historical), and discussion (Anime Discussion, Manga, Recommendations, News, Fan Creations, General) — but the underlying mechanism is generic tagging and filtering: any post can carry one or more categories from any group.
- Registration and login with bcrypt-hashed passwords and UUID cookie-based sessions (one active session per user, timestamps always UTC).
- Create posts with one or more categories; comment on posts.
- Like/dislike posts and comments, with live counts visible to everyone; liking a post you've already liked removes the reaction, disliking it replaces the like.
- Filter the post feed by category, by "my posts", or by "posts I've liked" (registered users only).
- Visitors (logged-out users) can read all posts and comments but cannot post, comment, or react.
- Progressive, framework-free JavaScript enhancements (logout confirmation, relative timestamps, a post-body character counter, and scroll position restoration) — the site is fully functional with JavaScript disabled.
- Go 1.22+ (standard library
net/http, method-aware routing) - SQLite via
mattn/go-sqlite3(CGO) golang.org/x/crypto/bcryptfor password hashinggoogle/uuidfor session tokens- Server-rendered HTML (
html/template), no frontend framework - Docker for containerized builds/runs
- Go 1.22+
- A C compiler (
gcc) — required for themattn/go-sqlite3CGO bindings - Docker (for containerized runs)
make(optional — every command below has a plain Go/Docker equivalent)
The module is already initialized and committed (go.mod, go.sum) — clone and fetch, don't
re-run go mod init:
git clone <repo-url> && cd forum
go mod download| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
Port the server listens on |
DB_PATH |
./forum.db |
Path to the SQLite database file |
SECURE_COOKIES |
off | Set true only when serving over HTTPS; must stay off for local HTTP — a Secure cookie is silently dropped by the browser over plain HTTP |
An empty value for PORT or DB_PATH is treated the same as unset — both fall back to their default
rather than producing an invalid value.
Every task below is a plain Go (or Docker) command on the left, and its make shortcut on the
right. Neither is required — pick whichever you prefer; the make targets exist to save typing and
keep flags consistent, not to hide anything. Run make help at any time for the full target list.
go run ./cmd/servermake run # same, reading PORT/DB_PATH from your shell
make run PORT=9090 # override any variable on the command line
make dev # same as run, with SECURE_COOKIES explicitly offThen visit http://localhost:8080 (or your chosen PORT).
go build -o server ./cmd/servermake buildgo fmt ./... && go vet ./... && go test ./... -v -cover -racemake test-cover # identical, one command
make check # the CI-safe variant: gofmt -l (fails loudly instead of
# rewriting files) + go vet + go test -race, no -v/-cover noise
make test # go test ./... only
make test-race # go test ./... -race onlyRun a single test the same way either path — there's no shortcut for this one, since it's inherently a one-off:
go test ./internal/auth/... -run TestHashPassword -vgo fmt ./... # rewrites files in place
gofmt -l . # lists unformatted files without changing them
go vet ./...make fmt # go fmt ./...
make fmt-check # gofmt -l ., non-zero exit if anything is unformatted
make vet # go vet ./...
make lint # fmt-check + vetgo test ./... -coverprofile=coverage.txt
go tool cover -html=coverage.txt -o coverage.htmlmake cover-htmldocker build -t forum:latest .
docker run -d --name forum -p 8080:8080 forum:latestmake docker # build + run together
make docker-build # build only
make docker-run # run only (replaces any existing container of the same name)Then visit http://localhost:8080, same as the local run.
docker rm -f forummake docker-stop # stop and remove the running containerdocker rm -f forum
docker rmi forum:latestmake docker-clean # stop the container and remove its imagerm -f server coverage.txt coverage.html forum.db
go cleanmake cleanDocker artifacts (image and container) are cleaned up separately — see make docker-clean above.
go mod tidy
go mod verifymake tidy| Method | Path | Auth required |
|---|---|---|
GET |
/ |
No |
GET |
/posts/{id} |
No |
GET, POST |
/register |
No |
GET, POST |
/login |
No |
POST |
/logout |
Yes |
GET |
/posts/new |
Yes |
POST |
/posts |
Yes |
POST |
/posts/{id}/comments |
Yes |
POST |
/posts/{id}/like, /posts/{id}/dislike |
Yes |
POST |
/comments/{id}/like, /comments/{id}/dislike |
Yes |
GET |
/static/* |
No |
Every route is registered with Go 1.22's method-aware mux patterns, so a request with the wrong
method gets an automatic 405 rather than falling into handler code.
cmd/server/ entry point, wires database/auth/content together
internal/auth/ password hashing, sessions, cookie middleware, auth routes
internal/content/ posts, comments, categories, reactions
internal/database/ SQLite connection setup and schema
internal/models/ shared data types (User, Post, Comment, Category, ...)
internal/webutil/ shared template rendering and error responses
web/templates/ HTML templates
web/static/ CSS and JS assets
AGENTS.md— guidance for AI coding assistants working in this repoCONTRIBUTING.md— workflow, branching, and commit conventionsCHANGELOG.md— release notesLICENSE— project license