▍ humdrum codex / custard
license AGPL-3.0
6.0 KB raw

custard — build plan

A custom, public-facing web code forge over my self-hosted Soft Serve git server. Own design — not a skinned cgit/gitweb. Reads bare repos directly; renders my own templates. Aesthetic = Bubble Tea / Charm terminal vibe + _shared-app-kit tokens (Flexoki / Uchu / Humdrum themes, Awke / Untitled Sans / Name Mono fonts).

Soft Serve is the git host (SSH push/TUI, read-only HTTP clone, webhooks). custard is a separate read-only Go web app pointed at the same bare repos on disk. It never writes git.

Decisions (locked)

Layout

custard/
├─ cmd/custard/main.go        flags/env, http.Server, graceful shutdown
├─ internal/
│  ├─ config/                 REPOS_PATH, SOFT_SERVE_HTTP, LISTEN_ADDR, BASE_URL
│  ├─ gitread/                go-git wrappers: list, refs, tree, blob, log, commit, archive
│  ├─ backlog/                parse backlog/tasks/*.md → Task{frontmatter + md body}
│  ├─ render/                 chroma highlight, goldmark md, byte/lang detection
│  └─ server/                 handlers, routes, middleware, error pages
├─ web/
│  ├─ templates/*.templ       layout, list, repo, tree, blob, log, commit, refs, issues, issue
│  └─ static/
│     ├─ tokens.css           ported from _shared-app-kit (Next bits stripped)
│     ├─ custard.css          app chrome — terminal/Charm look on the token system
│     ├─ theme.js             data-theme cookie toggle (7 modes)
│     └─ fonts/               Awke, Untitled Sans, Name Mono (.woff2)
├─ Caddyfile
├─ deploy/                    systemd unit + release.sh
├─ go.mod  PLAN.md  CLAUDE.md

URL scheme (cgit-inspired)

Route View
/ repo list (public, non-hidden) — name, description, last commit
/r/<repo> repo home: README render + branch/tag/commit summary
/r/<repo>/tree/<ref>/<path> directory browse
/r/<repo>/blob/<ref>/<path> file view — chroma highlight, or goldmark for .md
/r/<repo>/raw/<ref>/<path> raw bytes
/r/<repo>/log/<ref> commit log (paged)
/r/<repo>/commit/<sha> commit diff
/r/<repo>/refs branches + tags
/r/<repo>/issues backlog tasks, GitHub-issues style — filter by status/label
/r/<repo>/issues/<id> single task: rendered body + acceptance criteria
/dl/<repo>/<file>.tar.gz release tarball (phase 4)
/git/<repo>.git/* clone — Caddy reverse-proxy → Soft Serve HTTP (deploy)

Backlog → issues view (the GitHub-issues surface)

Issues already travel in-repo at backlog/tasks/*.md (YAML frontmatter + Markdown body), so no separate data source — go-git reads them from the chosen ref like any other file.

Phases

  1. Read layer + core views — go-git wrappers + handlers for list, repo, tree, blob, log, commit, refs. Unstyled HTML. Point at a local clone of ./repos/*.git for dev.
  2. Issues viewinternal/backlog parser + /issues list and detail.
  3. Styling pass — port tokens.css + fonts, build custard.css (terminal/Charm chrome), theme switcher (7 modes, cookie, no-flash SSR), polish all views.
  4. Homebrew tap + release pipelinegit archive tag → name-X.Y.Z.tar.gz in /dl + sha256; homebrew-tap repo in Soft Serve; GoReleaser emits formula, ~10-line script bumps url/sha256/version and pushes the tap. Source-build formula (no GitHub, no bottles).
  5. Deploy — Caddyfile (auto-TLS), systemd unit, reverse-proxy /git/* → Soft Serve :23232, serve /dl. Run on droplet next to Soft Serve's data dir.

Dev commands (target)

go install github.com/a-h/templ/cmd/templ@latest   # one-time: templ generator
templ generate                                      # .templ → _templ.go
go run ./cmd/custard --repos ./repos --addr :8080   # local dev
go build -o custard ./cmd/custard                    # release binary

Open / later