Contributing
This guide covers how to build, test, and contribute to AI Admin Panel.
Prerequisites
- Go 1.25+
- Node.js 20+ and npm
- Docker and Docker Compose
- PostgreSQL 16 (for local development, or use Docker)
- Git
Repository Structure
ai-admin-panel/
cmd/panel/
main.go # Application entry point
embed.go # Frontend embedding directive
frontend/dist/ # Embedded frontend build (committed)
internal/
api/ # HTTP handlers, middleware, router
domain/ # Business logic by domain
repository/ # Database queries (sqlc)
worker/ # Async job workers
templates/ # Template catalog and loader
frontend/
src/ # React application source
package.json
vite.config.ts
scripts/
build.sh # Safe build script
install.sh # Production installer
docker-compose.yml # Production compose
Build Process
Always use the build script:
# Build for current platform
./scripts/build.sh
# Cross-compile for Linux amd64 (production/VPS)
./scripts/build.sh --linux
# Build and verify the embedded frontend contains expected content
./scripts/build.sh --verify
The build script performs these steps:
- Builds the frontend:
cd frontend && npm run build - Copies the build output:
cp -r frontend/dist cmd/panel/frontend/dist - Compiles the Go binary:
CGO_ENABLED=0 go build -o panel ./cmd/panel/ - (With
--verify) Checks that the embedded JS contains expected strings
Never run go build ./cmd/panel/ without first copying the frontend build to cmd/panel/frontend/dist/. The Go binary embeds the frontend via //go:embed all:frontend/dist in cmd/panel/embed.go.
Local Development
Backend
# Run all Go tests
go test ./...
# Build and run locally
go build -o panel ./cmd/panel/
./panel
Frontend
cd frontend
# Install dependencies
npm install
# Start dev server (with hot reload)
npm run dev
# Type-check without emitting
npx tsc --noEmit
# Production build
npm run build
The frontend dev server proxies API requests to the Go backend. Configure the proxy target in vite.config.ts.
Testing
Go Tests
# Run all tests
go test ./...
# Run tests for a specific package
go test ./internal/templates/...
# Run with verbose output
go test -v ./...
# Run with race detector
go test -race ./...
All 24+ packages must pass. Template tests validate that all 45 YAML specs load and generate valid compose configurations.
TypeScript
cd frontend
# Type-check (must produce zero errors)
npx tsc --noEmit
# Build (must succeed)
npm run build
Playwright E2E
cd frontend
# Install browsers (first time)
npx playwright install
# Run all E2E tests
npx playwright test
# Run with UI mode
npx playwright test --ui
# Run a specific test file
npx playwright test tests/deploy.spec.ts
E2E tests run headless against the live panel and cover login, template browsing, deployment, and settings.
Required Checks
| Check | Command | When |
|---|---|---|
| Go compilation | go build ./... | Every backend change |
| Go tests | go test ./... | Every backend change |
| TypeScript types | cd frontend && npx tsc --noEmit | Every frontend change |
| Frontend build | cd frontend && npm run build | Every frontend change |
| Template validation | go test ./internal/templates/... | Every template change |
| Full build | ./scripts/build.sh --verify | Before deploy |
Git Workflow
Branches
| Branch | Purpose |
|---|---|
main | Stable, always deployable — protected |
v{X.Y}-dev | Milestone development branch |
gsd/phase-{N}-{slug} | Per-phase feature branches |
Rules
- Never commit directly to
main— use a dev branch + pull request - Push to origin frequently — do not accumulate many unpushed commits
- Tag releases when deploying:
git tag v1.X.Y - Never force-push to shared branches
Commit Messages
Use conventional commits:
feat(templates): add Mattermost template
fix(deploy): handle missing health check endpoint
refactor(api): extract service handler to separate file
test(backup): add restore workflow integration test
docs(readme): update installation instructions
Format: type(scope): description
Types: feat, fix, refactor, test, docs, chore, perf, ci
Code Conventions
Go
- Domain-driven directory structure under
internal/domain/ - sqlc for all database queries — write SQL in
internal/repository/queries/ - Interface-based dependency injection
- River
{Job}Args+{Job}Workerpattern for async jobs - Error wrapping with context:
fmt.Errorf("loading template %s: %w", name, err)
TypeScript/React
- Feature-based directory structure under
frontend/src/features/ - React Query for all server state
- shadcn/ui components for consistent UI
- Prefer named exports over default exports
- Use TypeScript strict mode — no
anytypes
Templates
- YAML specs in
internal/templates/catalog/{category}/ - Must include:
compose,variables,minResources,healthcheck,expose - No
ports:directive in compose (Traefik routing only) securityProfile: secureby default- Test with:
go test ./internal/templates/...
Adding a New Template
- Create a YAML file in
internal/templates/catalog/{category}/{name}.yaml - Follow the template structure documented in Template Overview
- Add a logo SVG in the logos directory
- Run template tests:
go test ./internal/templates/... - Build and verify:
./scripts/build.sh --verify
Submitting Changes
- Create a branch from the current dev branch
- Make your changes
- Run all relevant tests (see Required Checks above)
- Commit with a conventional commit message
- Push to origin
- Open a pull request against the dev branch