Files
bamort/.github/copilot-instructions.md
T
Bardioc26 042a1d4773 Learncost frontend (#42)
* introduced central package  registry by package init function
* dynamic registration of routes, model, migrations and initializers.
* setting a docker compose project name to prevent shutdown of other containers with the same (composer)name
* ai documentation
* app template
* Create tests for ALL API entpoints in ALL packages Based on current data. Ensure that all API endpoints used in frontend are tested. These tests are crucial for the next refactoring tasks.
* adopting agent instructions for a more consistent coding style
* added desired module layout and debugging information
* Fix All Failing tests All failing tests are fixed now that makes the refactoring more easy since all tests must pass
* restored routes for maintenance
* added common translations
* added new tests for API Endpoint
* Merge branch 'separate_business_logic'
* added lern and skill improvement cost editing
* Set Docker image tag when building to prevent rebuild when nothing has changed
* add and remove PP for Weaponskill fixed
* add and remove PP for same named skills fixed
* add new task
2026-05-01 18:15:31 +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