chore: remove agents.md
This commit is contained in:
172
AGENTS.md
172
AGENTS.md
@@ -1,172 +0,0 @@
|
||||
# mal
|
||||
|
||||
personal anime tracking platform. go/htmx rewrite.
|
||||
|
||||
## stack
|
||||
|
||||
- go standard library (`net/http`)
|
||||
- htmx + templ templates
|
||||
- sqlite + sqlc
|
||||
- tailwind (dark theme)
|
||||
- jikan api (myanimelist)
|
||||
|
||||
## structure
|
||||
|
||||
```
|
||||
cmd/server/ main entry
|
||||
internal/
|
||||
auth/ sessions, passwords
|
||||
database/ sqlc generated, migrations
|
||||
handlers/ http handlers by domain
|
||||
middleware/ auth, logging
|
||||
jikan/ api client
|
||||
templates/ templ components
|
||||
migrations/ sql files
|
||||
static/ css, js
|
||||
```
|
||||
|
||||
## go patterns
|
||||
|
||||
### errors
|
||||
|
||||
always handle errors explicitly. wrap with context using `fmt.Errorf`:
|
||||
|
||||
```go
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch user: %w", err)
|
||||
}
|
||||
```
|
||||
|
||||
use `errors.Is` and `errors.As` to check wrapped errors.
|
||||
|
||||
### early returns
|
||||
|
||||
reduce nesting. check errors first, return early:
|
||||
|
||||
```go
|
||||
func getUser(id string) (*User, error) {
|
||||
if id == "" {
|
||||
return nil, ErrInvalidID
|
||||
}
|
||||
|
||||
user, err := db.FindUser(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
```
|
||||
|
||||
### defer for cleanup
|
||||
|
||||
always close resources with defer:
|
||||
|
||||
```go
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
```
|
||||
|
||||
### interfaces
|
||||
|
||||
accept interfaces, return structs. keep interfaces small:
|
||||
|
||||
```go
|
||||
type Reader interface {
|
||||
Read(p []byte) (n int, err error)
|
||||
}
|
||||
```
|
||||
|
||||
### naming
|
||||
|
||||
- short, lowercase package names: `auth`, `jikan`, `db`
|
||||
- `MixedCaps` for exports, `mixedCaps` for internal
|
||||
- getters: `Owner()` not `GetOwner()`
|
||||
- interfaces: single method = method name + `er` suffix (`Reader`, `Writer`)
|
||||
|
||||
### zero values
|
||||
|
||||
design structs so zero value is useful:
|
||||
|
||||
```go
|
||||
var buf bytes.Buffer // ready to use, no init needed
|
||||
buf.WriteString("hello")
|
||||
```
|
||||
|
||||
### composition over inheritance
|
||||
|
||||
embed types to compose behavior:
|
||||
|
||||
```go
|
||||
type Handler struct {
|
||||
db *database.Queries
|
||||
jikan *jikan.Client
|
||||
logger *slog.Logger
|
||||
}
|
||||
```
|
||||
|
||||
## htmx
|
||||
|
||||
check for htmx requests:
|
||||
|
||||
```go
|
||||
func isHTMX(r *http.Request) bool {
|
||||
return r.Header.Get("HX-Request") == "true"
|
||||
}
|
||||
```
|
||||
|
||||
return partials for htmx, full pages otherwise. use `hx-swap-oob` for multiple updates. trigger toasts with `HX-Trigger` header.
|
||||
|
||||
## templ
|
||||
|
||||
render components directly to response:
|
||||
|
||||
```go
|
||||
func (h *Handler) Home(w http.ResponseWriter, r *http.Request) {
|
||||
templates.HomePage(data).Render(r.Context(), w)
|
||||
}
|
||||
```
|
||||
|
||||
pass data explicitly. keep components focused. use layouts.
|
||||
|
||||
## database
|
||||
|
||||
sqlc generates type-safe queries. always use parameterized queries.
|
||||
|
||||
tables: `user`, `session`, `account`, `anime`, `watch_list_entry`
|
||||
|
||||
watch statuses: `watching`, `completed`, `on_hold`, `dropped`, `plan_to_watch`
|
||||
|
||||
## jikan api
|
||||
|
||||
rate limit: 3 req/sec max. stagger batch requests. cache in local db.
|
||||
|
||||
## commands
|
||||
|
||||
```bash
|
||||
make dev # hot reload (air)
|
||||
make build # binary
|
||||
make test # tests
|
||||
make migrate # run migrations
|
||||
make sqlc # generate code
|
||||
make create-user # cli user creation
|
||||
```
|
||||
|
||||
## env
|
||||
|
||||
```bash
|
||||
DATABASE_FILE=mal.db
|
||||
SESSION_SECRET=min_32_chars_random
|
||||
PORT=3000
|
||||
```
|
||||
|
||||
## avoid
|
||||
|
||||
- panics in handlers
|
||||
- forgetting `defer resp.Body.Close()`
|
||||
- unstaggered jikan requests (429 errors)
|
||||
- globals for config/state
|
||||
- large monolithic templates
|
||||
Reference in New Issue
Block a user