and debugging information
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:
- Happy path — expected 2xx response with correct body
- Error / not-found path — expected 4xx response
- 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 onlyadmin; returns 403 for all other rolesuser.RequireMaintainer()— allowsmaintainerandadmin; returns 403 otherwise- Apply these as Gin middleware in
routes.goon 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
/apiprefix 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
bamort-backend-dev: Go API at http://localhost:8180 (Air live-reload)bamort-frontend-dev: Vue at http://localhost:5173 (Vite HMR)bamort-mariadb-dev: MariaDB at localhost:3306bamort-phpmyadmin-dev: http://localhost:8082
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
chromedpfor 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
- NEVER write example/demo code - only production code
- NEVER create test files with
main()- use_test.go - ALWAYS check
docker psbefore assuming containers are running - ALWAYS use TDD: write failing test first, then implement
- 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