Vendor pinned prettier/format toolchain from prompts scaffold (closes #203)
script/fmt ran unpinned npx prettier with an inline --tab-width and no config, so formatting was not reproducible. This vendors the canonical format toolchain from the prompts scaffold: .prettierrc (tabWidth 4, proseWrap always), package.json and yarn.lock pinning prettier 3.8.1, and a script/bootstrap that installs node/yarn from a hash-verified nvm archive. script/fmt now reads the config over static/js and markdown; gofmt/goimports unchanged. .prettierignore keeps the *.min.js rule protecting the vendored alpine.min.js. Existing markdown was reflowed to house style. Disclosure: make check does not gate prettier; the linter's pre-existing gomodguard deprecation warning is unrelated and left as-is. Model: opus-4-8 (implementation and review)
This commit was merged in pull request #204.
This commit is contained in:
+37
-31
@@ -1,6 +1,8 @@
|
||||
# Go HTTP Server Conventions
|
||||
|
||||
This document defines the architectural patterns, design decisions, and conventions for building Go HTTP servers. All new projects must follow these standards.
|
||||
This document defines the architectural patterns, design decisions, and
|
||||
conventions for building Go HTTP servers. All new projects must follow these
|
||||
standards.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
@@ -25,18 +27,18 @@ This document defines the architectural patterns, design decisions, and conventi
|
||||
|
||||
These libraries are **mandatory** for all new projects:
|
||||
|
||||
| Purpose | Library | Import Path |
|
||||
|---------|---------|-------------|
|
||||
| Dependency Injection | Uber fx | `go.uber.org/fx` |
|
||||
| HTTP Router | go-chi | `github.com/go-chi/chi` |
|
||||
| Logging | slog (stdlib) | `log/slog` |
|
||||
| Configuration | Viper | `github.com/spf13/viper` |
|
||||
| Environment Loading | godotenv | `github.com/joho/godotenv/autoload` |
|
||||
| CORS | go-chi/cors | `github.com/go-chi/cors` |
|
||||
| Error Reporting | Sentry | `github.com/getsentry/sentry-go` |
|
||||
| Metrics | Prometheus | `github.com/prometheus/client_golang` |
|
||||
| Metrics Middleware | go-http-metrics | `github.com/slok/go-http-metrics` |
|
||||
| Basic Auth | basicauth-go | `github.com/99designs/basicauth-go` |
|
||||
| Purpose | Library | Import Path |
|
||||
| -------------------- | --------------- | ------------------------------------- |
|
||||
| Dependency Injection | Uber fx | `go.uber.org/fx` |
|
||||
| HTTP Router | go-chi | `github.com/go-chi/chi` |
|
||||
| Logging | slog (stdlib) | `log/slog` |
|
||||
| Configuration | Viper | `github.com/spf13/viper` |
|
||||
| Environment Loading | godotenv | `github.com/joho/godotenv/autoload` |
|
||||
| CORS | go-chi/cors | `github.com/go-chi/cors` |
|
||||
| Error Reporting | Sentry | `github.com/getsentry/sentry-go` |
|
||||
| Metrics | Prometheus | `github.com/prometheus/client_golang` |
|
||||
| Metrics Middleware | go-http-metrics | `github.com/slok/go-http-metrics` |
|
||||
| Basic Auth | basicauth-go | `github.com/99designs/basicauth-go` |
|
||||
|
||||
---
|
||||
|
||||
@@ -85,7 +87,8 @@ project-root/
|
||||
### Key Principles
|
||||
|
||||
- **`cmd/{appname}/`**: Only the entry point. Minimal logic, just bootstrapping.
|
||||
- **`internal/`**: All application packages. Not importable by external projects.
|
||||
- **`internal/`**: All application packages. Not importable by external
|
||||
projects.
|
||||
- **One package per concern**: config, database, handlers, middleware, etc.
|
||||
- **Flat handler files**: One file per handler or logical group of handlers.
|
||||
|
||||
@@ -190,7 +193,8 @@ Providers are resolved automatically by fx, but conceptually follow this order:
|
||||
2. `logger.New` - Logger (depends on Globals)
|
||||
3. `config.New` - Configuration (depends on Globals, Logger)
|
||||
4. `database.New` - Database (depends on Logger, Config)
|
||||
5. `healthcheck.New` - Health check (depends on Globals, Config, Logger, Database)
|
||||
5. `healthcheck.New` - Health check (depends on Globals, Config, Logger,
|
||||
Database)
|
||||
6. `middleware.New` - Middleware (depends on Logger, Globals, Config)
|
||||
7. `handlers.New` - Handlers (depends on Logger, Globals, Database, Healthcheck)
|
||||
8. `server.New` - Server (depends on all above)
|
||||
@@ -453,7 +457,8 @@ func New(lc fx.Lifecycle, params HandlersParams) (*Handlers, error) {
|
||||
|
||||
### Closure-Based Handler Pattern
|
||||
|
||||
All handlers return `http.HandlerFunc` using the closure pattern. This allows initialization logic to run once when the handler is created:
|
||||
All handlers return `http.HandlerFunc` using the closure pattern. This allows
|
||||
initialization logic to run once when the handler is created:
|
||||
|
||||
```go
|
||||
// internal/handlers/index.go
|
||||
@@ -510,7 +515,8 @@ func (s *Handlers) decodeJSON(w http.ResponseWriter, r *http.Request, v interfac
|
||||
### Handler Naming Convention
|
||||
|
||||
- `HandleIndex()` - Main page
|
||||
- `HandleLoginGET()` / `HandleLoginPOST()` - Form handlers with HTTP method suffix
|
||||
- `HandleLoginGET()` / `HandleLoginPOST()` - Form handlers with HTTP method
|
||||
suffix
|
||||
- `HandleNow()` - API endpoints
|
||||
- `HandleHealthCheck()` - System endpoints
|
||||
|
||||
@@ -733,7 +739,8 @@ func New(lc fx.Lifecycle, params ConfigParams) (*Config, error) {
|
||||
|
||||
1. **Environment variables** (highest priority via `AutomaticEnv()`)
|
||||
2. **`.env` file** (loaded via `godotenv/autoload` import)
|
||||
3. **Config files**: `/etc/{appname}/{appname}.yaml`, `~/.config/{appname}/{appname}.yaml`
|
||||
3. **Config files**: `/etc/{appname}/{appname}.yaml`,
|
||||
`~/.config/{appname}/{appname}.yaml`
|
||||
4. **Defaults** (lowest priority)
|
||||
|
||||
### Environment Loading
|
||||
@@ -1005,6 +1012,7 @@ var Static embed.FS
|
||||
```
|
||||
|
||||
Directory structure:
|
||||
|
||||
```
|
||||
static/
|
||||
├── static.go
|
||||
@@ -1045,15 +1053,13 @@ Templates use Go's template composition:
|
||||
|
||||
```html
|
||||
<!-- index.html -->
|
||||
{{ template "htmlheader.html" . }}
|
||||
{{ template "navbar.html" . }}
|
||||
{{ template "htmlheader.html" . }} {{ template "navbar.html" . }}
|
||||
|
||||
<main>
|
||||
<!-- Page content -->
|
||||
</main>
|
||||
|
||||
{{ template "pagefooter.html" . }}
|
||||
{{ template "htmlfooter.html" . }}
|
||||
{{ template "pagefooter.html" . }} {{ template "htmlfooter.html" . }}
|
||||
```
|
||||
|
||||
### Static Asset References
|
||||
@@ -1214,12 +1220,12 @@ if viper.GetString("METRICS_USERNAME") != "" {
|
||||
|
||||
### Environment Variables Summary
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `PORT` | HTTP listen port | 8080 |
|
||||
| `DEBUG` | Enable debug logging | false |
|
||||
| `DBURL` | Database connection URL | "" |
|
||||
| `SENTRY_DSN` | Sentry DSN for error reporting | "" |
|
||||
| `MAINTENANCE_MODE` | Enable maintenance mode | false |
|
||||
| `METRICS_USERNAME` | Basic auth username for /metrics | "" |
|
||||
| `METRICS_PASSWORD` | Basic auth password for /metrics | "" |
|
||||
| Variable | Description | Default |
|
||||
| ------------------ | -------------------------------- | ------- |
|
||||
| `PORT` | HTTP listen port | 8080 |
|
||||
| `DEBUG` | Enable debug logging | false |
|
||||
| `DBURL` | Database connection URL | "" |
|
||||
| `SENTRY_DSN` | Sentry DSN for error reporting | "" |
|
||||
| `MAINTENANCE_MODE` | Enable maintenance mode | false |
|
||||
| `METRICS_USERNAME` | Basic auth username for /metrics | "" |
|
||||
| `METRICS_PASSWORD` | Basic auth password for /metrics | "" |
|
||||
|
||||
Reference in New Issue
Block a user