# Wavelet Agent Index This file is the project-level guide for agents working in Wavelet. More specialized workflows still live in `.agent/skills/`. ## Always Read The Matching Skill - `new-async-task`: use when adding or changing Asynq tasks, scheduled jobs, task metadata, task payload validation, task logs, task retry behavior, or Admin task APIs. - `new-setting`: use when adding or changing startup config, database-backed system/business/public settings, `/admin/system` parameters, or `/admin/settings` graphical settings. - Go skills: use the focused `go-*` skills for Go implementation details such as testing, error handling, packages, context, concurrency, logging, documentation, and review. - `shadcn`: use when adding, changing, or composing shadcn/ui components. ## Non-Negotiable Project Guardrails - Do not delete `frontend/node_modules`; reinstall with `pnpm install` if dependencies need refreshing. - Keep `internal/util/` framework-free. Do not import Gin, GORM, sessions, or other HTTP/framework packages from `internal/util/` or its subpackages. - Register all HTTP routes only in `internal/router/router.go`. - Update Swagger (`make swagger`) when API handlers change. - Run `make code-check` before submitting changes. ## Quick Commands | Command | When | | --- | --- | | `make code-check` | Required before submit | | `make build-test` | Functional build verification | | `make swagger` | After adding/changing APIs | | `make build-embedded` | Release binary with embedded frontend | | `make license` | After adding Go files | | `make license-check` | CI/license validation | # Wavelet Project Development Guide Use this guide for ordinary Wavelet development. If the task is specifically about Asynq/background/scheduled tasks, use `new-async-task` as the detailed workflow. ## Tech Stack - Backend: Go 1.25+, Gin, GORM, PostgreSQL, optional ClickHouse, Redis, Asynq, Cobra, Viper, Swaggo, OpenTelemetry, Zap, AWS SDK v2, Snowflake IDs. - Frontend: Next.js App Router, TypeScript, Tailwind CSS, pnpm, shadcn/ui. ## Directory Map Top level: - `main.go`: program entry, delegates to `internal/cmd`. - `config.example.yaml`: committed config template. Keep it updated when adding config fields. - `config.yaml`: local runtime config. Do not treat it as committed source. - `docker/`: integrated, frontend-only, and backend-only Dockerfiles. - `docs/`: generated Swagger docs. Do not hand edit generated files. - `frontend/`: Next.js app. - `internal/`: private Go backend code. - `scripts/`: local and CI helper scripts. - `support-files/`: auxiliary deployment files. Backend: - `internal/cmd/`: Cobra commands for API, worker, scheduler, root init. - `internal/config/`: Viper loading and config structs. Runtime code should use `config.Config.
.`. - `internal/router/`: the only HTTP route registration point. - `internal/apps/`: feature modules and HTTP handlers. - `internal/model/`: GORM entities and model-level business methods. - `internal/db/`: PostgreSQL, Redis, ClickHouse, GORM logging, ID generation, and AutoMigrate wiring. - `internal/storage/`: S3-compatible storage and cache abstraction. - `internal/task/`: Asynq task framework; see `new-async-task` for changes. - `internal/service/`: complex business services when handlers/models are too narrow a home. - `internal/common/`: shared response, bind, constants, and common errors. - `internal/util/`: pure utilities with no framework imports. - `internal/logger/`: Zap and OTel logging helpers. - `internal/listener/`: event listeners and message/webhook consumers. - `internal/otel_trace/`: tracing helpers. Frontend: - `frontend/app/`: App Router pages, route groups, root layout, globals. - `frontend/components/ui/`: shadcn/ui base components. - `frontend/components/common/`: cross-page business components. - `frontend/components/layout/`: Header, Sidebar, Footer, app layout pieces. - `frontend/components/auth/`, `home/`, `animate-ui/`, `providers/`: scoped UI. - `frontend/contexts/`, `hooks/`, `lib/`, `types/`, `public/`: shared state, hooks, clients/utilities, TypeScript types, static assets. Important common components: - `components/common/admin/tasks.tsx`: task dispatch UI. - `components/common/admin/task-executions.tsx`: task execution log/retry UI. - `components/common/admin/system.tsx`: system config management. - `components/common/admin/users.tsx`: user management. - `components/common/general/manage-pannel.tsx`: generic list/detail manager. - `components/common/general/password-dialog.tsx`: sensitive-action password confirmation dialog. - `components/common/settings/system-settings.tsx`: admin system settings. ## Backend Rules Naming: - Go packages and files use lowercase snake words: `auth_source`, `postgres_logger.go`. - Exported Go identifiers use PascalCase; unexported identifiers use camelCase. - Request/response structs use camelCase with suffixes like `listUsersRequest` and `listUsersResponse`. - Error message constants are camelCase string `const` values, not package-level `error` values. - YAML config keys use lowercase snake case. Handlers: - Handler names are verb + noun, for example `ListUsers`. - Bind with `ShouldBindQuery` or `ShouldBindJSON`. - Return success through `util.OK(data)`, `util.OKNil()`, or `response.RespondSuccess`. - Return failures with `util.Err(msg)` or `response.RespondFailure`. - API responses must have the outer shape `{ "error_msg": "", "data": ... }`. - Pagination responses use `{ "total": 0, "results": [] }` under `data`. - Every HTTP API needs complete Swagger comments; run `make swagger` after API changes. Routes and modules: - Register routes only in `internal/router/router.go`. - In `internal/apps//`, use: - `routers.go` or `controllers.go` for HTTP handlers. - `middlewares.go` for module-specific middleware. - `errs.go` for string error constants only. - `constants.go` for non-error business constants. - For Admin modules, prefer `internal/apps/admin//`. - If a handler file exceeds 600 lines, contains complex multi-step logic, or mixes independent domains, split business logic into `logic.go` or `logics.go`. Keep `routers.go` to binding, calling logic, and responding. Middleware: - Global middleware belongs in router setup: `gin.Recovery()`, `otelgin.Middleware()`, logger middleware, and session middleware. - Use `oauth.LoginRequired()` for logged-in route groups. - Use `admin.LoginAdminRequired()` for Admin route groups. Config: - Runtime code reads config from `config.Config`, never directly from `os.Getenv()`. - When adding config, update both `config.example.yaml` and `internal/config/model.go`. Database: - Simple queries may use GORM directly from the model layer. - Admin code should prefer `db.DB(ctx)` to get tracing-aware DB access. - Do not put complex SQL in handlers; move it to `internal/model/` or `internal/service/`. - Use AutoMigrate wiring under `internal/db/migrator/`; do not add manual DDL. - Do not create physical database foreign keys. Add explicit indexes for relation fields instead. - Database defaults must match Go model zero values (`nil`, `0`, `false`, `""`) to avoid surprising inserts. Strict dependency guard: - `internal/util/` and its subpackages must stay framework-free. - Do not import `github.com/gin-gonic/gin`, `gorm.io/gorm`, `github.com/gin-contrib/sessions`, or HTTP middleware/framework packages from `internal/util/`. - If utility logic needs web glue, keep pure validation/calculation in `internal/util/` and put Gin middleware/response handling in `internal/apps/`. Admin module workflow: 1. Define or extend models in `internal/model/`. 2. Register AutoMigrate changes under `internal/db/migrator/`. 3. Create `internal/apps/admin//routers.go` and optional `errs.go`. 4. Register routes in `internal/router/router.go`. 5. Run `make swagger`. ## Frontend Rules Styling: - shadcn/ui base components should use their `variant` system and global CSS variables. Do not hardcode colors, backgrounds, or shadows in business `className` when a component variant should own the look. - If an existing variant is insufficient, extend the shadcn/ui component variant instead of hardcoding one-off colors. - Use Lucide icons for common icon needs. Put custom icons in `frontend/components/icons/` as named exports. Page width: - Page root containers must support full width. Use `w-full`. - Do not hardcode page-level max widths like `max-w-6xl` or `max-w-4xl`; the main layout owns the normal/full-width constraint. Component placement: - Cross-page business components belong in `frontend/components/common/`. - shadcn/ui primitives belong in `frontend/components/ui/`. - Route/page-specific components belong in the closest feature directory. Type safety: - Do not use `any`. - Use `unknown` only with explicit narrowing or type assertions before use. - Use `never` sparingly and document why when it is non-obvious. - Frontend changes must pass TypeScript and ESLint checks. Services: - Frontend API access goes through service classes and the exported `services` object. - Create new services as: ```text frontend/lib/services// types.ts .service.ts index.ts ``` - Service classes extend `BaseService`, define `basePath`, and expose typed static methods. - Register the new service in `frontend/lib/services/index.ts`. ## Quality Gates - `make code-check`: required before submit; frontend typecheck + ESLint and backend golangci-lint. - `make build-test`: build verification for frontend and Go backend. - `make swagger`: regenerate Swagger after API changes. - `make build-embedded`: release binary with frontend static export embedded. - `make license`: run after adding Go files. - `make license-check`: validate Go license headers. Never delete `frontend/node_modules`; refresh dependencies with `pnpm install`.