2af477397e
I hope that coding results will be better and more consistent
5.7 KiB
5.7 KiB
Bamort Development Instructions
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
Each domain module follows this pattern (e.g., character/, pdfrender/, equipment/):
module/
handlers.go # HTTP handlers (Gin controllers)
routes.go # Route registration: RegisterRoutes(r *gin.RouterGroup)
*_test.go # Tests with setupTestEnvironment(t)
Key conventions:
- Entry point:
cmd/main.goregisters all modules viaRegisterRoutes(protected) - Models:
models/contains GORM entities (e.g.,Char,SkFertigkeit,EqWaffe) - Database: Shared
database.DBinstance, usemodels.MigrateStructure(db)for migrations - Configuration:
config.Cfgloaded from env vars (seeconfig/config.go)TEMPLATES_DIRfor PDF templates (default:./templates)ENVIRONMENT=test|development|productionDATABASE_TYPE=mysql|sqlite
Testing Requirements
- NEVER create test files with
main()functions - ALWAYS use
_test.gosuffix - ALWAYS call
setupTestEnvironment(t)at start of each test:func setupTestEnvironment(t *testing.T) { original := os.Getenv("ENVIRONMENT") os.Setenv("ENVIRONMENT", "test") t.Cleanup(func() { /* restore */ }) } - Use
testutils.SetupTestDB()for database tests (creates SQLite test DB) - Test character ID 18 (Fanjo Vetrani) exists in test database
API Patterns
- Protected routes under
/apiprefix require JWT authentication - Use
respondWithError(c, status, message)for error responses - Route registration example:
func RegisterRoutes(r *gin.RouterGroup) { group := r.Group("/module") group.GET("/list", ListHandler) group.POST("/create", CreateHandler) }
Frontend Architecture (frontend/)
Component Structure
- Views:
src/views/- Page-level components (CharacterView, DashboardView) - Components:
src/components/- Reusable components (CharacterDetails, SkillView) - Utils:
src/utils/api.js- Axios instance with JWT interceptor - Locales:
src/locales/deandsrc/locales/en- i18n translations (JS objects, not JSON) - Store: Pinia stores in
src/stores/
API Communication
- Use
API.get(),API.post()fromutils/api.js(auto-adds auth headers) - Base URL:
import.meta.env.VITE_API_URL(defaults tohttp://localhost:8180) - Example:
const response = await API.get(`/api/characters/${this.id}`)
Translation Pattern
Add to both locales/de and locales/en:
export default {
export: {
selectTemplate: 'Vorlage wählen', // DE
exportPDF: 'PDF Export'
}
}
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
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
}
Modal Dialogs (Frontend)
<div v-if="showDialog" class="modal-overlay" @click.self="showDialog = false">
<div class="modal-content"><!-- content --></div>
</div>
Popup Blocker Workaround
Open window synchronously before async calls:
const newWindow = window.open('', '_blank')
// ... then await API call ...
newWindow.location.href = url
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
- ALWAYS add translations to both DE and EN locales
- ALWAYS use global CSS definition to ensure consistent style
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 - js files: See
.github/instructions/js.instructions.md - css files: See
.github/instructions/css.instructions.md