GHAT(D) is an open-source, opinionated, and free full-stack web application foundation based on the Go programming language. Its name is an acronym that stands for Go, HTMX, Alpine.js, Tailwind, and DaisyUI, which originally formed the foundational stack. Over time, for improved usability, it has also been extended to support most Vite-compatible front-end stacks (tested with Vue). The aim is to make GHAT(D) a solid base for creating highly portable, scalable, and performant full-stack projects. Whether you need just a backend, a landing page, or a content-driven application, you can still utilise GHAT(D) without committing to a hidden application container.
We recognise that everyone has unique needs, and ideally their solutions should not start with a messy foundation that requires cleaning up before building. To reduce cognitive load and make preparation easier, we have introduced "building blocks" which we call Details. A Detail is an independent application that can function both within a GHAT(D) project and on its own. GHAT(D) supports api, web, and web-vite Detail types.
GHAT(D) is a hobby project I work on in my spare time. It is designed to provide a friendly starting point for people like me who are interested in Go, APIs, and web applications, and who want a consistent foundation and shared standards to build from. I hope GHAT(D) can serve as an ejectable base for many awesome projects and initiatives.
I also aim to use this project as a learning opportunity, to improve my understanding of and share my knowledge of lightweight frontend libraries, highly portable full-stack alternatives, and cost-effective infrastructure solutions for full-scale products.
As we develop this project, I want to also create tutorials/guides for those who want to integrate it with other technologies, such as rpc, graphql, websocket, and others.
I am a platform engineer by trade, so I do not promise perfect code by any stretch of the imagination (especially with the front end - so please support and contribute). Instead, I am aspiring to create a standardised project base that helps those curious (about Go, APIs, hobby projects, and web app development) to turn their ideas/ hobbies into tangible product(s) that they can demo and even ship.
This will be an exciting experience, and I look forward to building out this project with you all and sharing my progress and knowledge as it matures.
GHAT(D) offers modular packages that can be used both together and independently. Our goal is for each package to adhere to clean architecture principles, featuring comprehensive documentation and examples. We are committed to implementing these practices in both new and legacy packages, especially those that are less extensible for other projects.
A dual-channel verification system providing both magic link and human-readable code entry.
- Access Manager - Complete authentication and authorisation with email-based verification, login, OAuth, and API token management
accessmanager- User creation, login, registration, email verification, OAuth, API token managementaccessmanager/middleware- JWT, API token, rate-limiting, and hardened code-verification middlewareaccessmanager/helpers- Context-transmission utilities and unique code generationauth- JWT creation, validation, and metadata extractionapitoken- API token lifecycle management
A complete email solution split into three composable packages for maximum flexibility and testability.
- Email Manager - Complete email system with templating, sending, and audit logging
emailtemplater- Generate HTML email templates with variable substitutionemailprovider- Abstract email sending across providers (SparkPost, logging, custom)emailmanager- High-level orchestration with audit integration
A complete billing solution split into three composable packages for maximum flexibility and testability.
- Billing Manager - Complete billing system with webhook processing, subscription management, and audit logging
paymentprovider- Abstract payment provider webhook verification and payload normalisation (Stripe, Lemon Squeezy, Ko-fi)billing- Manage subscription and billing event data persistence with repository patternbillingmanager- High-level orchestration with webhook processing and audit integration
- Pricer - Source-of-truth pricing catalog with plans, feature entitlements, provider refs, Mongo migrations, and pricing-card E2E fixtures
pricer- Manage pricing plans, costs, features, and provider-linked catalog metadata
- Audit - Handles audit logging for compliance and debugging
- Content Manager - HTTP orchestration for CMS-style content
- Group - User groups, memberships, and hierarchical organisations
- Logger - Structured logging with middleware support
- MongoDB Migrator - Shared migration command with host-owned registrations and templates
- Notifier - Push notification registration, preferences, and delivery
- Post - Reusable content models, persistence, and publication rules
- Reminder - User-owned scheduled reminders with target-based lookups and execution tracking
- Router - Shared HTTP routing and route attachment
- SEO - Sitemap generation and persistence
- SPA - Single-page application serving and fallback routing
- Streaker - Generic idempotent streak completions, current/best stats, and history listing
- Repository - MongoDB repository patterns and utilities
- Server - Ejectable HTTP server lifecycle helper with graceful shutdown
- Starter/v0 - Ejectable lazy composition layer for GHATD application wiring
- User v2 - Configurable universal user model and persistence
- User Manager - User-facing orchestration across user, group, reminder, and related services
- Vision - Feedback and roadmap management
- Error Manifest - Cross-package error mapping and bundle composition Note on Core Packages: This is a curated overview rather than an exhaustive package inventory. Each documented package keeps its canonical README alongside the package code.
GHAT(D) supports a dual-channel verification flow for login and email verification — users receive both a magic link (with a JWT token) and an 8-character alphanumeric code in the same email.
- Email delivery: Both login and verification emails contain a clickable magic link AND a human-readable 8-character code displayed in large monospaced font.
- Link flow (
?t=<jwt-token>): User clicks the magic link → token is validated → user is authenticated. - Code flow (
?c=ABCD1234): User enters the code in the app or web interface ("I already have a session code") → code is resolved to its corresponding token via ephemeral storage → token is validated → user is authenticated. - Code generation: Each code is globally unique (A-Z, 0-9), crypto-random, stored in ephemeral storage with a TTL matching the token expiry, and regenerated on collision.
| Layer | Mechanism |
|---|---|
| Code entropy | 8-character A-Z/0-9 = ~2.8 trillion combinations |
| Collision resistance | Ephemeral storage check with up to 5 retry attempts |
| Brute-force protection | HardenedRateLimitProtection middleware tracks attempts per IP and per code within a configurable window (default: 5/hr per IP, 5/hr per code) |
| Auto-blocking | IPs exceeding the threshold are temporarily blocked (default: 1 hour) |
| One-time use | Codes and tokens are invalidated after successful verification |
| Time-bounded | Login tokens default to 5 minutes; email-verification tokens default to 10 minutes |
| Refresh rotation tolerance | Near-concurrent duplicate refreshes can reuse the winning rotation result instead of consuming the same refresh token twice |
| Login email cooldown | Duplicate login email sends for the same active user/context are suppressed during a short cooldown window |
| Audit logging | All verification attempts (pass and fail) and rate-limit blocks are logged for monitoring |
| Rate-limit response | Blocked IPs receive HTTP 429 with EPH0-002 — no information leakage |
Before getting started please make sure you have the correct version of Go installed or you can use asdf to install the pinned toolchain from .tool-versions. Minimum required Go version: 1.26.4.
# Add the plugin for Go
asdf plugin add golang
# Install the pinned version
asdf installUse asdf exec when running maintenance commands so local validation uses the same Go toolchain as the repository:
asdf exec go test ./...
asdf exec go run golang.org/x/vuln/cmd/govulncheck@v1.3.0 ./...
asdf exec go mod tidyRun the source version of the CLI with the repository's pinned toolchain:
asdf exec go run cli/cli.go --helpInspect a command before using it:
asdf exec go run cli/cli.go <desired-command> --helpThe new command can assemble a host application from one or more Details, but the generator remains experimental and its defaults may target development branches or module versions. Review the generated application and run asdf exec go mod tidy before relying on it. Generated applications include a host-owned cmd/mongo-migrator adapter and migrations/mongo/template.go; the adapter keeps using GHATD's shared migration implementation while its host imports are rewritten to the new module.
Example local command:
asdf exec go run cli/cli.go new \
-n "awesome-service" \
-m "github.com/example/awesome-service" \
-w "github.com/example/ghatd-detail-api"See About Details and Getting Started With A New Project for the supported Detail types and generated-app workflow. See Managing MongoDB Migrations before adding or applying migrations.
To start the server you can use the code:
asdf exec go run main.go start-serverFor a better development experience, install reflex to rerun the server command when files change:
reflex -r '\.(html|go|css|png|svg|ico|js|woff2|woff|ttf|eot)$' -s -- asdf exec go run main.go start-serverAll ASCII art in this template was created using PatorJK.
- Making a
GETrequest:curl -i -X GET "http://localhost:4000/v0/health/check"
Add a blank index.html file to the specific directory that you want to disable listings for. For example, the code below will create an index file which will stop the web app from showing and listing page.
touch internal/web/ui/static/index.htmlInstall reflex
asdf exec go install github.com/cespare/reflex@latest
You can find more information in the repo https://github.com/cespare/reflex
Once installed, run the server
reflex -r '\.(html|go|css|png|svg|ico|js|woff2|woff|ttf|eot)$' -s -- asdf exec go run main.go start-serverOne of the benefits of using the GHATD stack is that it compiles everything into a single binary. This makes it highly portable and provides numerous deployment options.
To build a binary for the GHATDCLI for your desired system architecture, please follow the instructions below:
All commands should be executed from the root directory.
export BINARY_NAME=ghatdcli
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 asdf exec go build -a -installsuffix cgo -ldflags="-w -s" -o ./$BINARY_NAME cli/cli.goexport BINARY_NAME=ghatdcli
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 asdf exec go build -a -installsuffix cgo -ldflags="-w -s" -o ./$BINARY_NAME cli/cli.goexport BINARY_NAME=ghatdcli
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 asdf exec go build -a -installsuffix cgo -ldflags="-w -s" -o ./$BINARY_NAME cli/cli.goexport BINARY_NAME=ghatdcli
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 asdf exec go build -a -installsuffix cgo -ldflags="-w -s" -o ./$BINARY_NAME cli/cli.goTo build a binary for web app to your desired system architecture, please follow the instructions below:
All commands should be executed from the root directory.
export BINARY_NAME=ghatd
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 asdf exec go build -a -installsuffix cgo -ldflags="-w -s" -o ./$BINARY_NAME main.goexport BINARY_NAME=ghatd
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 asdf exec go build -a -installsuffix cgo -ldflags="-w -s" -o ./$BINARY_NAME main.goexport BINARY_NAME=ghatd
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 asdf exec go build -a -installsuffix cgo -ldflags="-w -s" -o ./$BINARY_NAME main.goexport BINARY_NAME=ghatd
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 asdf exec go build -a -installsuffix cgo -ldflags="-w -s" -o ./$BINARY_NAME main.goThis project is licensed under the MIT License.
