Files
bamort/.github/copilot-instructions.md
Frank c7908663d6 added desired module layout
and debugging information
2026-04-12 08:06:49 +02:00

7.1 KiB

Bamort Development Instructions

READ THIS FILE CAREFULLY AND COMPLETE BEFORE STARTING DEVELOPMENT!

Bamort is a role-playing game character management system (MOAM replacement) with a Go backend and Vue.js frontend.

Project Overview

  • Repository: github.com:Bardioc26/bamort.git
  • Architecture: Monorepo with separate backend/frontend in Docker containers
  • Backend: Go 1.25 + Gin framework + GORM + MariaDB
  • Frontend: Vue 3 + Vite + i18n
  • Development: Docker Compose with live-reload (Air for Go, Vite HMR for Vue)

Backend Architecture (backend/)

Module Structure

Every backend module must contain exactly these files:

File Required Content
handlers.go yes All HTTP handler functions for the module (Gin controllers)
routes.go yes Route definitions; calls RegisterRoutes
register.go yes init() — registers routes, models, and migrations with the application
model.go yes GORM entity definitions owned by this module
*_test.go yes At least one test file; more files allowed by sub-domain
database.go when needed Module-specific DB query helpers

Handler files may be split by sub-domain (e.g. lerncost_handler.go, share_handlers.go) when handlers.go grows large. The split files stay in the same package.

Models: each module defines its own GORM entities in model.go. The shared models/ package contains only types that are referenced across multiple modules.

Configuration: config.Cfg loaded from env vars — ENVIRONMENT, DATABASE_TYPE, TEMPLATES_DIR, etc.

Route Ownership Map

New endpoints must be added to the module that owns their prefix. the prefixes can be foundin the routes.go files.

Use RequireAdmin() or RequireMaintainer() middleware on sub-routes that need elevated roles — never check roles inside a handler.

Module Dependencies

Modules should be self contained as far as possible. If a module needs to reference another module's data, it should import that module's package and use its exported functions — do not duplicate logic or data structures. If this means circular references, consider whether the shared logic should be moved to a common package (e.g. utils/ or models/) of an exeption for duplicating logic or data structures must be made.

Testing Requirements

  • NEVER create test files with main() — always use _test.go
  • ALWAYS call setupTestEnvironment(t) at the top of every test function
  • Use testutils.SetupTestDB() for any test that touches the database (creates an isolated SQLite DB)
  • Test character ID 18 (Fanjo Vetrani) is pre-seeded in the test DB

Every handler must have tests covering:

  1. Happy path — expected 2xx response with correct body
  2. Error / not-found path — expected 4xx response
  3. Unauthorized access — expected 401 (no token) or 403 (wrong role) for protected routes

Use t.Run("scenario", ...) subtests when a handler has multiple input variants. Group related scenarios in one table-driven test rather than writing separate top-level test functions.

Role Checking

Roles in ascending order: standard < maintainer < admin.

  • user.RequireAdmin() — allows only admin; returns 403 for all other roles
  • user.RequireMaintainer() — allows maintainer and admin; returns 403 otherwise
  • Apply these as Gin middleware in routes.go on a sub-group — never read the role inside a handler
func RegisterRoutes(r *gin.RouterGroup) {
    group := r.Group("/maintenance")
    group.GET("/skills", listSkills)          // all authenticated users

    protected := group.Group("")
    protected.Use(user.RequireMaintainer())
    protected.POST("/skills", createSkill)    // maintainer + admin only
}

API Patterns

  • Protected routes under /api prefix require JWT — user.AuthMiddleware() is applied globally
  • Use respondWithError(c, status, message) for all error responses

Docker Development Workflow

Verify Containers

docker ps | grep bamort-backend-dev  # Must be running before testing

Container Names & Ports

Rebuild After Dockerfile Changes

cd /data/dev/bamort
docker-compose -f docker/docker-compose.dev.yml build bamort-backend-dev
docker-compose -f docker/docker-compose.dev.yml up -d bamort-backend-dev

View Logs

docker logs bamort-backend-dev --tail=50
docker logs bamort-frontend-dev --tail=20

Testing Commands

Backend Tests

cd /data/dev/bamort/backend
go test -v ./pdfrender/ -run TestExportCharacterToPDF
go test -v ./character/

Frontend

  • HMR auto-reloads on file save
  • Check browser console and docker logs bamort-frontend-dev

Debugging & Bugfixing

Both Docker containers are always running. Use them directly — no restart needed.

Read live logs (Air/Vite output, compile errors, runtime panics):

docker logs bamort-backend-dev -f --tail=50
docker logs bamort-frontend-dev -f --tail=20

Test API endpoints directly:

# Public — no token needed
curl -s http://localhost:8180/api/public/version

# Authenticated — copy token from browser DevTools → Application → localStorage → 'token'
curl -s -H "Authorization: Bearer <token>" http://localhost:8180/api/characters

Inspect database: phpMyAdmin at http://localhost:8082

Backend test failures run against an isolated SQLite DB (testutils.SetupTestDB()) — they are independent of the running MariaDB container.

Air recompiles the backend automatically on file save — compile errors appear immediately in docker logs bamort-backend-dev.

Vite HMR reloads the frontend on file save — build errors appear in docker logs bamort-frontend-dev and the browser console.

PDF Rendering Module (pdfrender/)

  • Uses chromedp for HTML→PDF (requires Chromium in Docker)
  • Templates in templates/Default_A4_Quer/ (page1_stats.html, page2_play.html, etc.)
  • Continuation pages auto-generated for overflow (page1.2_stats.html pattern)
  • Test with character ID 18: generates 4 pages + continuations if needed
  • Template capacity defined in HTML comments: <!-- MaxItems: 58 -->

Common Patterns

Error Handling (Backend)

if err != nil {
    c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
    return
}

Critical Rules

  1. NEVER write example/demo code - only production code
  2. NEVER create test files with main() - use _test.go
  3. ALWAYS check docker ps before assuming containers are running
  4. ALWAYS use TDD: write failing test first, then implement
  5. ALWAYS use KISS principle: simplest solution that works

File-Specific Instructions

Load additional instructions for specific file types:

  • Go files: See .github/instructions/go.instructions.md
  • Vue files: See .github/instructions/vue.instructions.md
  • CSS files: See .github/instructions/css.instructions.md
  • JS files: See .github/instructions/js.instructions.md