Skip to main content

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:

  1. Builds the frontend: cd frontend && npm run build
  2. Copies the build output: cp -r frontend/dist cmd/panel/frontend/dist
  3. Compiles the Go binary: CGO_ENABLED=0 go build -o panel ./cmd/panel/
  4. (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

CheckCommandWhen
Go compilationgo build ./...Every backend change
Go testsgo test ./...Every backend change
TypeScript typescd frontend && npx tsc --noEmitEvery frontend change
Frontend buildcd frontend && npm run buildEvery frontend change
Template validationgo test ./internal/templates/...Every template change
Full build./scripts/build.sh --verifyBefore deploy

Git Workflow

Branches

BranchPurpose
mainStable, always deployable — protected
v{X.Y}-devMilestone 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}Worker pattern 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 any types

Templates

  • YAML specs in internal/templates/catalog/{category}/
  • Must include: compose, variables, minResources, healthcheck, expose
  • No ports: directive in compose (Traefik routing only)
  • securityProfile: secure by default
  • Test with: go test ./internal/templates/...

Adding a New Template

  1. Create a YAML file in internal/templates/catalog/{category}/{name}.yaml
  2. Follow the template structure documented in Template Overview
  3. Add a logo SVG in the logos directory
  4. Run template tests: go test ./internal/templates/...
  5. Build and verify: ./scripts/build.sh --verify

Submitting Changes

  1. Create a branch from the current dev branch
  2. Make your changes
  3. Run all relevant tests (see Required Checks above)
  4. Commit with a conventional commit message
  5. Push to origin
  6. Open a pull request against the dev branch