4.0 KiB
4.0 KiB
CaddyProxyManager+ Copilot Instructions
🚨 CRITICAL ARCHITECTURE RULES 🚨
- Single Frontend Source: All frontend code MUST reside in
frontend/. NEVER createbackend/frontend/or any other nested frontend directory. - Single Backend Source: All backend code MUST reside in
backend/. - No Python: This is a Go (Backend) + React/TypeScript (Frontend) project. Do not introduce Python scripts or requirements.
Big Picture
backend/cmd/apiloads config, opens SQLite, then hands off tointernal/serverwhere routes frominternal/api/routesare registered.internal/configrespectsCPM_ENV,CPM_HTTP_PORT,CPM_DB_PATH,CPM_FRONTEND_DIRand creates thedata/directory; lean on these instead of hard-coded paths.- All HTTP endpoints live under
/api/v1/*; keep new handlers insideinternal/api/handlersand register them viaroutes.Registersodb.AutoMigrateruns for their models. internal/serveralso mounts the built React app (viaattachFrontend) wheneverfrontend/distexists, falling back to JSON{"error": ...}for any/api/*misses.- Persistent types live in
internal/models; GORM auto-migrates them each boot, so evolve schemas there before touching handlers or the frontend.
Backend Workflow
- Run locally with
cd backend && go run ./cmd/api; run tests withgo test ./...(seeproxy_host_handler_test.gofor the in-memory SQLite/Gin harness pattern). - Handlers return structured errors using
gin.H{"error": "message"}and standard HTTP codes—mirror theProxyHostHandlerlifecycle for new CRUD endpoints. - UUIDs (
github.com/google/uuid) are generated server-side and exposed asuuidfields; clients never send numeric IDs. - Query lists sorted by
updated_at desc(see.Order("updated_at desc")inList); match that ordering for user-visible collections. - Long-running work must respect the graceful shutdown flow in
server.Run(ctx)—avoid background goroutines that ignore the context.
Frontend Workflow
- Location: Always work within
frontend/. - Stack: React 18 + Vite + TypeScript + TanStack Query (React Query).
- State Management: Use
src/hooks/use*.tswrapping React Query. Do not use rawuseEffectfor data fetching. - API Layer: Create typed API clients in
src/api/*.tsthat wrapclient.ts. - Development: Run
cd frontend && npm run dev. Vite proxies/apitohttp://localhost:8080. - Components: Screens live in
src/pages. Reusable UI insrc/components. - Forms: Use local
useStatefor form fields, submit viauseMutationfrom custom hooks, theninvalidateQuerieson success.
Cross-Cutting Notes
- Run the backend before the frontend; React Query expects the exact JSON produced by GORM tags (snake_case), so keep API and UI field names aligned.
- When adding models, update both
internal/modelsand theAutoMigratecall insideinternal/api/routes/routes.go; register new Gin routes right after migrations for clarity. - Tests belong beside handlers (
*_test.go); reuse thesetupTestRouterhelper structure (in-memory SQLite, Gin router, httptest requests) for fast feedback. - Testing Requirement: All new code (features, bug fixes, refactors) MUST include accompanying unit tests. Ensure tests cover happy paths and error conditions.
- Ignore Files: When creating new file types, directories, or build artifacts, ALWAYS check and update
.gitignore,.dockerignore, and.codecov.ymlto ensure they are properly excluded or included as required. - The root
Dockerfilebuilds the Go binary and the React static assets (multi-stage build). - Branch from
feature/**and targetdevelopment.
CI/CD & Commit Conventions
- Docker Builds: The
docker-publishworkflow skips builds for commits starting withchore:. - Triggering Builds: To ensure a new Docker image is built (e.g., for testing on VPS), use
feat:,fix:, orperf:prefixes. - Beta Branch: The
feature/beta-releasebranch is configured to ALWAYS build, overriding the skip logic.