Compare commits
No commits in common. "ffde8b1863477685e8ab1f87afd0b16a2ca8ca77" and "73ef86ceac67d3dc0b89b586ca216b9c1958c2fa" have entirely different histories.
ffde8b1863
...
73ef86ceac
22 changed files with 6475 additions and 18 deletions
37
.gitignore
vendored
37
.gitignore
vendored
|
|
@ -1,15 +1,11 @@
|
||||||
# ---> Node
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
lerna-debug.log*
|
lerna-debug.log*
|
||||||
.pnpm-debug.log*
|
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
||||||
|
|
||||||
# Runtime data
|
# Runtime data
|
||||||
pids
|
pids
|
||||||
|
|
@ -55,9 +51,6 @@ web_modules/
|
||||||
# Optional eslint cache
|
# Optional eslint cache
|
||||||
.eslintcache
|
.eslintcache
|
||||||
|
|
||||||
# Optional stylelint cache
|
|
||||||
.stylelintcache
|
|
||||||
|
|
||||||
# Microbundle cache
|
# Microbundle cache
|
||||||
.rpt2_cache/
|
.rpt2_cache/
|
||||||
.rts2_cache_cjs/
|
.rts2_cache_cjs/
|
||||||
|
|
@ -73,7 +66,7 @@ web_modules/
|
||||||
# Yarn Integrity file
|
# Yarn Integrity file
|
||||||
.yarn-integrity
|
.yarn-integrity
|
||||||
|
|
||||||
# dotenv environment variable files
|
# dotenv environment variables file
|
||||||
.env
|
.env
|
||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
|
|
@ -86,7 +79,6 @@ web_modules/
|
||||||
|
|
||||||
# Next.js build output
|
# Next.js build output
|
||||||
.next
|
.next
|
||||||
out
|
|
||||||
|
|
||||||
# Nuxt.js build / generate output
|
# Nuxt.js build / generate output
|
||||||
.nuxt
|
.nuxt
|
||||||
|
|
@ -101,13 +93,6 @@ dist
|
||||||
# vuepress build output
|
# vuepress build output
|
||||||
.vuepress/dist
|
.vuepress/dist
|
||||||
|
|
||||||
# vuepress v2.x temp and cache directory
|
|
||||||
.temp
|
|
||||||
.cache
|
|
||||||
|
|
||||||
# Docusaurus cache and generated files
|
|
||||||
.docusaurus
|
|
||||||
|
|
||||||
# Serverless directories
|
# Serverless directories
|
||||||
.serverless/
|
.serverless/
|
||||||
|
|
||||||
|
|
@ -130,3 +115,21 @@ dist
|
||||||
.yarn/install-state.gz
|
.yarn/install-state.gz
|
||||||
.pnp.*
|
.pnp.*
|
||||||
|
|
||||||
|
# Vite
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
# System files
|
||||||
|
Thumbs.db
|
||||||
64
.opencode-config.json
Normal file
64
.opencode-config.json
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
{
|
||||||
|
"project": {
|
||||||
|
"name": "bms-forge",
|
||||||
|
"description": "BattleMap Notation Schema (BMS) renderer for DnD/TTRPG maps",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"repository": "https://git.bouncypixel.com/helm/bms-forge.git",
|
||||||
|
"deploymentUrl": "maps.bouncypixel.com"
|
||||||
|
},
|
||||||
|
"userPreferences": {
|
||||||
|
"codingStyle": {
|
||||||
|
"typescript": "strict-types-minimal-anys",
|
||||||
|
"react": "pragmatic-balance",
|
||||||
|
"stateManagement": "context-first-upgrade-if-needed",
|
||||||
|
"errorHandling": "graceful-degradation-with-optional-libs",
|
||||||
|
"testing": "critical-paths-first-then-expand"
|
||||||
|
},
|
||||||
|
"architecture": {
|
||||||
|
"componentStructure": "type-based-with-domain-subfolders",
|
||||||
|
"styling": "tailwind-hybrid-with-css-modules",
|
||||||
|
"buildTool": "vite",
|
||||||
|
"canvasLibrary": "konva",
|
||||||
|
"validation": "zod",
|
||||||
|
"yamlParsing": "js-yaml",
|
||||||
|
"editor": "monaco"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"projectContext": {
|
||||||
|
"phase": "implementation",
|
||||||
|
"currentFocus": "project-initialized",
|
||||||
|
"decisionsMade": [
|
||||||
|
"Frontend-only MVP with React + TypeScript",
|
||||||
|
"Use BMS 1.0 schema as defined in docs/",
|
||||||
|
"Paperly style as default free tier",
|
||||||
|
"Texture packs as future monetization",
|
||||||
|
"AI integration as subscription feature",
|
||||||
|
"Initial deployment to maps.bouncypixel.com"
|
||||||
|
],
|
||||||
|
"nextSteps": [
|
||||||
|
"Create BMS TypeScript interfaces",
|
||||||
|
"Implement YAML parser and validator",
|
||||||
|
"Build basic rendering engine",
|
||||||
|
"Create editor and preview components",
|
||||||
|
"Implement export functionality"
|
||||||
|
],
|
||||||
|
"keyFiles": [
|
||||||
|
"docs/PROJECT_PLAN.md",
|
||||||
|
"docs/BMS_SCHEMA_SPEC.md",
|
||||||
|
"docs/IMPLEMENTATION_ROADMAP.md",
|
||||||
|
"docs/TECHNICAL_ARCHITECTURE.md",
|
||||||
|
".opencode-config.json"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"sessionNotes": {
|
||||||
|
"lastUpdated": "2026-03-19",
|
||||||
|
"developerProfile": "Senior software engineer and manager of small dev team. Prefers pragmatic TypeScript with strict types but willing to use 'any' when needed. State management depends on complexity. Open to functional error handling libraries but aware of learning curve. Tests critical paths first, expands coverage after features stabilize.",
|
||||||
|
"projectGoals": [
|
||||||
|
"V1: Frontend-only BMS renderer with Paperly style",
|
||||||
|
"Free forever for basic functionality",
|
||||||
|
"Monetize via texture packs and AI subscriptions",
|
||||||
|
"Build community around BMS schema format",
|
||||||
|
"Potential future VTT integration"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Lukas Parsons
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
108
QUICK_START.md
Normal file
108
QUICK_START.md
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
# BMS Forge - Quick Start Guide
|
||||||
|
|
||||||
|
## Project Context
|
||||||
|
|
||||||
|
### What is this?
|
||||||
|
A web-based BattleMap Notation Schema (BMS) renderer for DnD/TTRPG maps.
|
||||||
|
|
||||||
|
### Current Phase: Planning → Implementation
|
||||||
|
- **V1 Goal**: Frontend-only BMS renderer with "Paperly" style
|
||||||
|
- **Deployment**: maps.bouncypixel.com (alpha)
|
||||||
|
- **Tech Stack**: React + TypeScript + Konva.js + Zod + js-yaml
|
||||||
|
|
||||||
|
### Developer Preferences (Lukas)
|
||||||
|
- **TypeScript**: Strict types but pragmatic about `any`
|
||||||
|
- **State Management**: Context first, upgrade if needed
|
||||||
|
- **Error Handling**: Graceful degradation, open to functional libs
|
||||||
|
- **Testing**: Critical paths first, expand later
|
||||||
|
- **Components**: Type-based with domain subfolders
|
||||||
|
- **Styling**: Tailwind hybrid with CSS modules
|
||||||
|
- **Build**: Vite
|
||||||
|
|
||||||
|
## Getting Started (After Break)
|
||||||
|
|
||||||
|
1. **Check context**: Read `.opencode-config.json` and `docs/`
|
||||||
|
2. **Review decisions**: BMS schema format, tech stack, architecture
|
||||||
|
3. **Continue from**: Last completed task in roadmap
|
||||||
|
|
||||||
|
## Key Decisions Made
|
||||||
|
|
||||||
|
### Architecture
|
||||||
|
- **Frontend-only MVP**: No backend needed initially
|
||||||
|
- **BMS 1.0 Schema**: Defined in `docs/BMS_SCHEMA_SPEC.md`
|
||||||
|
- **Rendering Engine**: Konva.js with layered rendering
|
||||||
|
- **Validation**: Zod for runtime schema validation
|
||||||
|
- **Editor**: Monaco Editor for YAML editing
|
||||||
|
|
||||||
|
### Business Model
|
||||||
|
- **Free Tier**: Paperly style rendering
|
||||||
|
- **Monetization**: Texture packs + AI subscription
|
||||||
|
- **Community**: BMS schema as sharing format
|
||||||
|
|
||||||
|
### Deployment
|
||||||
|
- **Alpha**: maps.bouncypixel.com
|
||||||
|
- **Version Control**: Private Forgejo at git.bouncypixel.com
|
||||||
|
- **Future**: Potential custom domain (bms-forge.com)
|
||||||
|
|
||||||
|
## Next Immediate Actions
|
||||||
|
|
||||||
|
Based on current roadmap (`docs/IMPLEMENTATION_ROADMAP.md`):
|
||||||
|
|
||||||
|
### Week 1, Days 1-2: Project Setup
|
||||||
|
```bash
|
||||||
|
npm create vite@latest bms-forge -- --template react-ts
|
||||||
|
cd bms-forge
|
||||||
|
npm install konva react-konva js-yaml zod @monaco-editor/react
|
||||||
|
npm install tailwindcss postcss autoprefixer
|
||||||
|
npm install -D @types/js-yaml @types/node
|
||||||
|
```
|
||||||
|
|
||||||
|
### Project Structure to Create
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── types/ # BMS TypeScript interfaces
|
||||||
|
├── schema/ # Zod validation schemas
|
||||||
|
├── parser/ # YAML parsing utilities
|
||||||
|
├── renderer/ # Konva.js rendering engine
|
||||||
|
├── components/ # Type-based with domains
|
||||||
|
│ ├── layout/ # Header, Sidebar, etc.
|
||||||
|
│ ├── canvas/ # Map rendering components
|
||||||
|
│ ├── editor/ # YAML editor components
|
||||||
|
│ └── shared/ # Common UI components
|
||||||
|
├── hooks/ # Custom React hooks
|
||||||
|
├── utils/ # Helper functions
|
||||||
|
└── App.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
## When You Return
|
||||||
|
|
||||||
|
1. **Check status**: What was last completed?
|
||||||
|
2. **Read decisions**: Review config and docs
|
||||||
|
3. **Pick up**: Continue from next logical step
|
||||||
|
4. **Ask**: "What should we work on next?"
|
||||||
|
|
||||||
|
## Common Commands
|
||||||
|
```bash
|
||||||
|
# Development
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Build
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Type checking
|
||||||
|
npm run type-check
|
||||||
|
|
||||||
|
# Linting
|
||||||
|
npm run lint
|
||||||
|
```
|
||||||
|
|
||||||
|
## Questions to Consider When Continuing
|
||||||
|
|
||||||
|
1. **Parsing complete?** Can we parse BMS YAML yet?
|
||||||
|
2. **Rendering working?** Are rooms showing on canvas?
|
||||||
|
3. **UI usable?** Editor + preview layout functional?
|
||||||
|
4. **Testing needed?** Critical paths covered?
|
||||||
|
|
||||||
|
---
|
||||||
|
*Last Updated: 2026-03-19*
|
||||||
|
*Project: BMS Forge - BattleMap Generator*
|
||||||
179
README.md
179
README.md
|
|
@ -1,2 +1,179 @@
|
||||||
# bms-forge
|
# BMS Forge
|
||||||
|
|
||||||
|
> BattleMap Notation Schema (BMS) Renderer for DnD/TTRPG Maps
|
||||||
|
|
||||||
|
[](https://opensource.org/licenses/MIT)
|
||||||
|
[](https://www.typescriptlang.org/)
|
||||||
|
[](https://reactjs.org/)
|
||||||
|
[](https://vitejs.dev/)
|
||||||
|
|
||||||
|
A web-based tool for rendering and editing DnD/TTRPG battlemaps using the structured [Battlemap Notation Schema (BMS)](docs/BMS_SCHEMA_SPEC.md) format. Create, share, and customize battlemaps with a clean, semantic YAML-based format.
|
||||||
|
|
||||||
|
## ✨ Features
|
||||||
|
|
||||||
|
- **BMS Schema Support**: Parse and validate BMS 1.0 YAML files
|
||||||
|
- **Real-time Rendering**: Instant visual feedback as you edit
|
||||||
|
- **"Paperly" Style**: Clean, vector-style default theme (always free)
|
||||||
|
- **Export Options**: PNG, JSON, and BMS YAML formats
|
||||||
|
- **Future Plans**: Texture packs, AI generation, VTT integration
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
- Node.js 18+ and npm/yarn/pnpm
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
```bash
|
||||||
|
# Clone the repository
|
||||||
|
git clone ssh://git@git.bouncypixel.com:222/helm/bms-forge.git
|
||||||
|
cd bms-forge
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Start development server
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Visit `http://localhost:3000` to see the app in action.
|
||||||
|
|
||||||
|
### Build for Production
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
npm run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
bms-forge/
|
||||||
|
├── src/
|
||||||
|
│ ├── types/ # BMS TypeScript interfaces
|
||||||
|
│ ├── schema/ # Zod validation schemas
|
||||||
|
│ ├── parser/ # YAML parsing utilities
|
||||||
|
│ ├── renderer/ # Konva.js rendering engine
|
||||||
|
│ │ ├── layers/ # Individual layer renderers
|
||||||
|
│ │ └── styles/ # Paperly + texture pack styles
|
||||||
|
│ ├── components/ # React components (type-based)
|
||||||
|
│ │ ├── layout/ # Layout components
|
||||||
|
│ │ ├── canvas/ # Map rendering components
|
||||||
|
│ │ ├── editor/ # YAML editor components
|
||||||
|
│ │ └── shared/ # Common UI components
|
||||||
|
│ ├── hooks/ # Custom React hooks
|
||||||
|
│ ├── utils/ # Helper functions
|
||||||
|
│ ├── App.tsx
|
||||||
|
│ └── main.tsx
|
||||||
|
├── docs/ # Project documentation
|
||||||
|
├── public/ # Static assets
|
||||||
|
└── package.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Technology Stack
|
||||||
|
|
||||||
|
- **Frontend**: React 19 + TypeScript
|
||||||
|
- **Build Tool**: Vite
|
||||||
|
- **Canvas Rendering**: Konva.js
|
||||||
|
- **Validation**: Zod
|
||||||
|
- **YAML Parsing**: js-yaml
|
||||||
|
- **Code Editor**: Monaco Editor
|
||||||
|
- **Styling**: Tailwind CSS + CSS Modules
|
||||||
|
- **Linting**: ESLint + TypeScript ESLint
|
||||||
|
|
||||||
|
## 📋 Development
|
||||||
|
|
||||||
|
### Available Scripts
|
||||||
|
```bash
|
||||||
|
npm run dev # Start development server
|
||||||
|
npm run build # Build for production
|
||||||
|
npm run preview # Preview production build
|
||||||
|
npm run lint # Run ESLint
|
||||||
|
npm run type-check # TypeScript type checking
|
||||||
|
```
|
||||||
|
|
||||||
|
### Code Style
|
||||||
|
- TypeScript with strict mode (pragmatic about `any`)
|
||||||
|
- Functional components with hooks
|
||||||
|
- Type-based component organization
|
||||||
|
- Tailwind utilities for layout, CSS modules for complex styles
|
||||||
|
|
||||||
|
## 📚 BMS Schema
|
||||||
|
|
||||||
|
The Battlemap Notation Schema (BMS) is a YAML-based format for describing DnD/TTRPG battlemaps. See the [complete specification](docs/BMS_SCHEMA_SPEC.md).
|
||||||
|
|
||||||
|
### Example BMS File
|
||||||
|
```yaml
|
||||||
|
BMS Version: 1.0
|
||||||
|
Map Name: Guard Room
|
||||||
|
Grid Size: 20x15
|
||||||
|
Grid Unit: 5ft
|
||||||
|
Style: Stone Fortress
|
||||||
|
Lighting: Torchlight
|
||||||
|
|
||||||
|
ROOMS:
|
||||||
|
- R1: Guard Room (0,0)-(20,15)
|
||||||
|
Walls: Stone-1ft-Smooth
|
||||||
|
Floor: Flagstones
|
||||||
|
Ceiling: 15ft, wooden beams
|
||||||
|
|
||||||
|
DOORS:
|
||||||
|
- D1: Wooden Door (20,6)-(20,9)
|
||||||
|
Type: Wood-Single-Reinforced
|
||||||
|
Connects: R1 -> Corridor
|
||||||
|
State: Closed-Unlocked
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎯 Roadmap
|
||||||
|
|
||||||
|
### Phase 1: MVP (Current)
|
||||||
|
- [x] Project setup and structure
|
||||||
|
- [ ] BMS TypeScript interfaces and validation
|
||||||
|
- [ ] Basic YAML parsing
|
||||||
|
- [ ] Grid and room rendering
|
||||||
|
- [ ] Door and object rendering
|
||||||
|
- [ ] Export functionality
|
||||||
|
- [ ] Alpha deployment to maps.bouncypixel.com
|
||||||
|
|
||||||
|
### Phase 2: Texture Packs
|
||||||
|
- [ ] Texture pack system architecture
|
||||||
|
- [ ] Pack management UI
|
||||||
|
- [ ] Texture rendering engine
|
||||||
|
- [ ] Marketplace integration
|
||||||
|
|
||||||
|
### Phase 3: AI Integration
|
||||||
|
- [ ] OpenAI API integration
|
||||||
|
- [ ] Chat-based schema generation
|
||||||
|
- [ ] Iterative editing workflow
|
||||||
|
- [ ] Subscription system
|
||||||
|
|
||||||
|
### Phase 4: Community & VTT
|
||||||
|
- [ ] Template sharing
|
||||||
|
- [ ] VTT export (FoundryVTT, Roll20)
|
||||||
|
- [ ] User accounts
|
||||||
|
- [ ] Collaboration features
|
||||||
|
|
||||||
|
## 📄 License
|
||||||
|
|
||||||
|
MIT License - see [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
||||||
|
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
||||||
|
4. Push to the branch (`git push origin feature/amazing-feature`)
|
||||||
|
5. Open a Pull Request
|
||||||
|
|
||||||
|
## 📞 Contact
|
||||||
|
|
||||||
|
Project maintained by [Lukas Parsons](https://github.com/lukasparsons).
|
||||||
|
|
||||||
|
- **Project**: [BMS Forge](https://maps.bouncypixel.com) (coming soon)
|
||||||
|
- **Repository**: `ssh://git@git.bouncypixel.com:222/helm/bms-forge.git`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<i>Built with ❤️ for the TTRPG community</i>
|
||||||
|
</p>
|
||||||
463
docs/BMS_SCHEMA_SPEC.md
Normal file
463
docs/BMS_SCHEMA_SPEC.md
Normal file
|
|
@ -0,0 +1,463 @@
|
||||||
|
# Battlemap Notation Schema (BMS) - Technical Specification
|
||||||
|
|
||||||
|
## Schema Version: 1.0
|
||||||
|
|
||||||
|
## Complete Field Reference
|
||||||
|
|
||||||
|
### 1. Header Section (Required)
|
||||||
|
| Field | Type | Description | Example |
|
||||||
|
|-------|------|-------------|---------|
|
||||||
|
| `BMS Version` | String | Schema version | `"1.0"` |
|
||||||
|
| `Map Name` | String | Map title | `"Goblin Warrens"` |
|
||||||
|
| `Grid Size` | String | Width×Height in squares | `"40x30"` |
|
||||||
|
| `Grid Unit` | String | Feet per square | `"5ft"` |
|
||||||
|
| `Style` | String | Visual theme | `"Stone Cavern"` |
|
||||||
|
| `Lighting` | String | Ambient light | `"Dim (torchlight)"` |
|
||||||
|
| `Ambient Sound` | String | Background audio | `"Dripping water"` |
|
||||||
|
| `Temperature` | String | Environmental temp | `"55°F, damp"` |
|
||||||
|
|
||||||
|
### 2. Coordinate System
|
||||||
|
```
|
||||||
|
(0,0)───────→ x (width)
|
||||||
|
│
|
||||||
|
│
|
||||||
|
↓
|
||||||
|
y (height)
|
||||||
|
|
||||||
|
Example: (5,10) = column 6, row 11 (5ft squares)
|
||||||
|
Range: (x1,y1)-(x2,y2) defines rectangle
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Room Definition
|
||||||
|
```yaml
|
||||||
|
ROOMS:
|
||||||
|
- R1: [Room Name] (x1,y1)-(x2,y2)
|
||||||
|
Walls: [Material-Thickness-Style]
|
||||||
|
Floor: [Material-Texture]
|
||||||
|
Ceiling: [Height-Features]
|
||||||
|
Lighting: [Light sources within]
|
||||||
|
Features: [Special characteristics]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Wall Types:**
|
||||||
|
- `Stone-1ft-Rough`
|
||||||
|
- `Wood-6in-Carved`
|
||||||
|
- `Iron-2ft-Reinforced`
|
||||||
|
- `Masonry-1ft-Smooth`
|
||||||
|
- `Natural-Rockface`
|
||||||
|
|
||||||
|
**Floor Types:**
|
||||||
|
- `Rough stone, debris`
|
||||||
|
- `Packed earth`
|
||||||
|
- `Wooden planks`
|
||||||
|
- `Flagstones`
|
||||||
|
- `Mosaic tile`
|
||||||
|
|
||||||
|
### 4. Door Definition
|
||||||
|
```yaml
|
||||||
|
DOORS:
|
||||||
|
- D1: [Door Name]
|
||||||
|
Type: [Material-Single/Double-Style]
|
||||||
|
Position: (x1,y1)-(x2,y2)
|
||||||
|
Connects: [Room1] <-> [Room2]
|
||||||
|
State: [Open/Closed]-[Locked/Unlocked]
|
||||||
|
Hinges: [Side]
|
||||||
|
DC: [Difficulty if locked/trapped]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Door Types:**
|
||||||
|
- `Wood-Single-Banded`
|
||||||
|
- `Iron-Double-Portcullis`
|
||||||
|
- `Stone-Sliding-Secret`
|
||||||
|
- `Wood-Double-Ornate`
|
||||||
|
|
||||||
|
**States:**
|
||||||
|
- `Open-Unlocked`
|
||||||
|
- `Closed-Locked` (DC15)
|
||||||
|
- `Closed-Barred`
|
||||||
|
- `Destroyed`
|
||||||
|
|
||||||
|
### 5. Object Definition
|
||||||
|
```yaml
|
||||||
|
OBJECTS:
|
||||||
|
- O1: [Object Name]
|
||||||
|
Type: [Material-Type-Style]
|
||||||
|
Position: (x1,y1)-(x2,y2)
|
||||||
|
Elevation: [+/- ft from floor]
|
||||||
|
State: [Condition]
|
||||||
|
Contents: [What's inside]
|
||||||
|
Lock: [Lock details if applicable]
|
||||||
|
Trapped: [Trap details if applicable]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Object Types:**
|
||||||
|
- `Wood-Table-Rough`
|
||||||
|
- `Stone-Throne-Ornate`
|
||||||
|
- `Iron-Chest-Large`
|
||||||
|
- `Wood-Barrel-Sturdy`
|
||||||
|
- `Stone-Altar-Carved`
|
||||||
|
|
||||||
|
### 6. Hazard Definition
|
||||||
|
```yaml
|
||||||
|
HAZARDS:
|
||||||
|
- H1: [Hazard Name]
|
||||||
|
Type: [Mechanical/Magical/Environmental]-[Effect]
|
||||||
|
Position: (x1,y1)-(x2,y2)
|
||||||
|
Trigger: [Activation mechanism]
|
||||||
|
DC: [Perception/Disable DCs]
|
||||||
|
Save: [Saving throw type & DC]
|
||||||
|
Damage: [Damage dice]
|
||||||
|
Effect: [Additional effects]
|
||||||
|
Reset: [Manual/Automatic]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Hazard Types:**
|
||||||
|
- `Mechanical-Pit-20ft`
|
||||||
|
- `Magical-Glyph-Fire`
|
||||||
|
- `Environmental-Gas-Poison`
|
||||||
|
- `Mechanical-Dart-Pressure`
|
||||||
|
- `Magical-Fear-Aura`
|
||||||
|
|
||||||
|
### 7. Lighting Definition
|
||||||
|
```yaml
|
||||||
|
LIGHTING:
|
||||||
|
- L1: [Light Name]
|
||||||
|
Type: [Source-Type]
|
||||||
|
Position: (x,y)
|
||||||
|
Radius: [Bright ft, Dim ft]
|
||||||
|
Color: [Light color]
|
||||||
|
Fuel: [Duration/Fuel source]
|
||||||
|
Special: [Flickering/Steady etc]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Light Types:**
|
||||||
|
- `Torch-Wall`
|
||||||
|
- `Lantern-Hanging`
|
||||||
|
- `Candle-Table`
|
||||||
|
- `Magical-Everburning`
|
||||||
|
- `Fungi-Bioluminescent`
|
||||||
|
|
||||||
|
### 8. Connection Graph
|
||||||
|
```yaml
|
||||||
|
CONNECTIONS:
|
||||||
|
[Room1] -- [Door/Passage] --> [Room2]
|
||||||
|
[Room2] -- [Tunnel] --> [Room3]
|
||||||
|
[Room3] -- [Secret] --> [Room4]
|
||||||
|
```
|
||||||
|
|
||||||
|
**Connection Types:**
|
||||||
|
- `-- [Door] -->` (Standard door)
|
||||||
|
- `-- [Secret] -->` (Hidden passage)
|
||||||
|
- `-- [Tunnel] -->` (Long corridor)
|
||||||
|
- `-- [Stairs] -->` (Vertical connection)
|
||||||
|
|
||||||
|
### 9. Annotation Definition
|
||||||
|
```yaml
|
||||||
|
ANNOTATIONS:
|
||||||
|
- "[Text]" at (x,y)
|
||||||
|
- "[Label]" pointing to (x1,y1)-(x2,y2)
|
||||||
|
- "DM: [Note]" at (x,y)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Advanced Features
|
||||||
|
|
||||||
|
### Multi-level Maps
|
||||||
|
```yaml
|
||||||
|
ELEVATION:
|
||||||
|
- Base Level: 0ft
|
||||||
|
- Upper Balcony: +15ft
|
||||||
|
- Lower Pit: -20ft
|
||||||
|
|
||||||
|
STAIRS:
|
||||||
|
- S1: Spiral Stairs
|
||||||
|
Position: (25,15)-(27,17)
|
||||||
|
Connects: Level1 -> Level2 (+10ft)
|
||||||
|
Steps: 20
|
||||||
|
```
|
||||||
|
|
||||||
|
### Secret/Concealed Features
|
||||||
|
```yaml
|
||||||
|
SECRETS:
|
||||||
|
- S1: Hidden Door
|
||||||
|
Position: (14,12)-(14,14)
|
||||||
|
Type: Stone-Sliding
|
||||||
|
DC: 20 Perception
|
||||||
|
Mechanism: Lever at (12,18)
|
||||||
|
Revealed: When mechanism activated
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environmental Zones
|
||||||
|
```yaml
|
||||||
|
ZONES:
|
||||||
|
- Z1: Fog Bank
|
||||||
|
Position: (10,10)-(20,20)
|
||||||
|
Effect: Heavily obscured
|
||||||
|
Save: None
|
||||||
|
Movement: Normal
|
||||||
|
|
||||||
|
- Z2: Slippery Ice
|
||||||
|
Position: (30,30)-(40,40)
|
||||||
|
Effect: Difficult terrain
|
||||||
|
Save: DC 10 Acrobatics or fall prone
|
||||||
|
```
|
||||||
|
|
||||||
|
## Visualization Standards
|
||||||
|
|
||||||
|
### Color Coding (Suggested)
|
||||||
|
- **Walls:** Dark gray (#333333)
|
||||||
|
- **Doors:** Brown (#8B4513)
|
||||||
|
- **Hazards:** Red (#FF0000) with pattern
|
||||||
|
- **Objects:** Medium gray (#666666)
|
||||||
|
- **Light sources:** Yellow glow (#FFFF00)
|
||||||
|
- **Water:** Blue (#0000FF)
|
||||||
|
- **Difficult terrain:** Green diagonal lines
|
||||||
|
- **Elevation changes:** Contour lines
|
||||||
|
|
||||||
|
### Icon Standards
|
||||||
|
- **Door:** Rectangle with arc
|
||||||
|
- **Chest:** Rectangle with curved lid
|
||||||
|
- **Table:** Rectangle
|
||||||
|
- **Chair/T hrone:** Square with back
|
||||||
|
- **Torch:** Small circle with flame above
|
||||||
|
- **Pit:** Diagonal hatch pattern
|
||||||
|
- **Secret:** Dotted outline
|
||||||
|
|
||||||
|
## Example: Simple Guard Room
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
BMS Version: 1.0
|
||||||
|
Map Name: Guard Room
|
||||||
|
Grid Size: 20x15
|
||||||
|
Grid Unit: 5ft
|
||||||
|
Style: Stone Fortress
|
||||||
|
Lighting: Torchlight
|
||||||
|
|
||||||
|
ROOMS:
|
||||||
|
- R1: Guard Room (0,0)-(20,15)
|
||||||
|
Walls: Stone-1ft-Smooth
|
||||||
|
Floor: Flagstones
|
||||||
|
Ceiling: 15ft, wooden beams
|
||||||
|
Lighting: Wall torches at (3,0), (17,0)
|
||||||
|
|
||||||
|
DOORS:
|
||||||
|
- D1: Wooden Door (20,6)-(20,9)
|
||||||
|
Type: Wood-Single-Reinforced
|
||||||
|
Connects: R1 -> Corridor
|
||||||
|
State: Closed-Unlocked
|
||||||
|
Hinges: East side
|
||||||
|
|
||||||
|
OBJECTS:
|
||||||
|
- O1: Guard Table (5,5)-(9,9)
|
||||||
|
Type: Wood-Table-Sturdy
|
||||||
|
Contents: Maps, mugs, dice
|
||||||
|
|
||||||
|
- O2: Weapon Rack (15,5)-(17,10)
|
||||||
|
Type: Wood-Rack-Wall
|
||||||
|
Contents: 4 spears, 2 swords
|
||||||
|
|
||||||
|
LIGHTING:
|
||||||
|
- L1: Wall Torch (3,0)
|
||||||
|
Radius: 20ft bright, 40ft dim
|
||||||
|
Color: Orange flickering
|
||||||
|
|
||||||
|
- L2: Wall Torch (17,0)
|
||||||
|
Radius: 20ft bright, 40ft dim
|
||||||
|
Color: Orange flickering
|
||||||
|
|
||||||
|
ANNOTATIONS:
|
||||||
|
- "Guard post" at (10,7)
|
||||||
|
- "Weapons" pointing to O2
|
||||||
|
```
|
||||||
|
|
||||||
|
## TypeScript Interface Definition
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Core BMS Types
|
||||||
|
type Coordinate = [number, number]; // (x, y)
|
||||||
|
type Rectangle = { from: Coordinate; to: Coordinate };
|
||||||
|
|
||||||
|
interface BMSHeader {
|
||||||
|
bmsVersion: string;
|
||||||
|
mapName: string;
|
||||||
|
gridSize: { width: number; height: number };
|
||||||
|
gridUnit: string;
|
||||||
|
style: string;
|
||||||
|
lighting: string;
|
||||||
|
ambientSound?: string;
|
||||||
|
temperature?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Room {
|
||||||
|
id: string; // "R1"
|
||||||
|
name: string;
|
||||||
|
position: Rectangle;
|
||||||
|
walls: string; // "Stone-1ft-Rough"
|
||||||
|
floor: string; // "Rough stone, debris"
|
||||||
|
ceiling: string; // "15ft, wooden beams"
|
||||||
|
lighting?: string;
|
||||||
|
features?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Door {
|
||||||
|
id: string; // "D1"
|
||||||
|
name: string;
|
||||||
|
type: string; // "Wood-Single-Banded"
|
||||||
|
position: Rectangle;
|
||||||
|
connects: { room1: string; room2: string };
|
||||||
|
state: { open: boolean; locked: boolean; dc?: number };
|
||||||
|
hinges?: string; // "East side"
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MapObject {
|
||||||
|
id: string; // "O1"
|
||||||
|
name: string;
|
||||||
|
type: string; // "Wood-Table-Rough"
|
||||||
|
position: Rectangle;
|
||||||
|
elevation?: string; // "+2ft"
|
||||||
|
state?: string;
|
||||||
|
contents?: string;
|
||||||
|
lock?: string;
|
||||||
|
trapped?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Hazard {
|
||||||
|
id: string; // "H1"
|
||||||
|
name: string;
|
||||||
|
type: string; // "Mechanical-Pit-20ft"
|
||||||
|
position: Rectangle;
|
||||||
|
trigger?: string;
|
||||||
|
dc?: { perception?: number; disable?: number };
|
||||||
|
save?: { type: string; dc: number };
|
||||||
|
damage?: string;
|
||||||
|
effect?: string;
|
||||||
|
reset?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LightSource {
|
||||||
|
id: string; // "L1"
|
||||||
|
name: string;
|
||||||
|
type: string; // "Torch-Wall"
|
||||||
|
position: Coordinate;
|
||||||
|
radius: { bright: number; dim: number };
|
||||||
|
color?: string;
|
||||||
|
fuel?: string;
|
||||||
|
special?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Connection {
|
||||||
|
from: string; // Room ID
|
||||||
|
to: string; // Room ID
|
||||||
|
type: string; // "Door", "Secret", "Tunnel", "Stairs"
|
||||||
|
via?: string; // Door ID if applicable
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Annotation {
|
||||||
|
text: string;
|
||||||
|
position: Coordinate;
|
||||||
|
type?: "label" | "note" | "pointer";
|
||||||
|
target?: Rectangle; // For pointer annotations
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BMSSchema extends BMSHeader {
|
||||||
|
rooms?: Room[];
|
||||||
|
doors?: Door[];
|
||||||
|
objects?: MapObject[];
|
||||||
|
hazards?: Hazard[];
|
||||||
|
lightingSources?: LightSource[];
|
||||||
|
connections?: Connection[];
|
||||||
|
annotations?: Annotation[];
|
||||||
|
|
||||||
|
// Advanced features (future)
|
||||||
|
elevation?: Elevation[];
|
||||||
|
stairs?: Stairs[];
|
||||||
|
secrets?: Secret[];
|
||||||
|
zones?: Zone[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Parser Functions
|
||||||
|
|
||||||
|
### Grid Size Parser
|
||||||
|
```typescript
|
||||||
|
function parseGridSize(str: string): { width: number; height: number } {
|
||||||
|
// "40x30" → { width: 40, height: 30 }
|
||||||
|
const match = str.match(/^(\d+)x(\d+)$/);
|
||||||
|
if (!match) throw new Error(`Invalid grid size: ${str}`);
|
||||||
|
return { width: parseInt(match[1]), height: parseInt(match[2]) };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Coordinate Parser
|
||||||
|
```typescript
|
||||||
|
function parseCoordinate(str: string): Coordinate {
|
||||||
|
// "(5,10)" → [5, 10]
|
||||||
|
const match = str.match(/^\((\d+),(\d+)\)$/);
|
||||||
|
if (!match) throw new Error(`Invalid coordinate: ${str}`);
|
||||||
|
return [parseInt(match[1]), parseInt(match[2])];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rectangle Parser
|
||||||
|
```typescript
|
||||||
|
function parseRectangle(str: string): Rectangle {
|
||||||
|
// "(0,0)-(20,15)" → { from: [0,0], to: [20,15] }
|
||||||
|
const match = str.match(/^\((\d+),(\d+)\)-\((\d+),(\d+)\)$/);
|
||||||
|
if (!match) throw new Error(`Invalid rectangle: ${str}`);
|
||||||
|
return {
|
||||||
|
from: [parseInt(match[1]), parseInt(match[2])],
|
||||||
|
to: [parseInt(match[3]), parseInt(match[4])]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Door State Parser
|
||||||
|
```typescript
|
||||||
|
function parseDoorState(str: string): { open: boolean; locked: boolean; dc?: number } {
|
||||||
|
// "Open-Unlocked" → { open: true, locked: false }
|
||||||
|
// "Closed-Locked (DC15)" → { open: false, locked: true, dc: 15 }
|
||||||
|
const match = str.match(/^(Open|Closed)-(Unlocked|Locked)(?: \(DC(\d+)\))?$/);
|
||||||
|
if (!match) throw new Error(`Invalid door state: ${str}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
open: match[1] === "Open",
|
||||||
|
locked: match[2] === "Locked",
|
||||||
|
dc: match[3] ? parseInt(match[3]) : undefined
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Validation Rules
|
||||||
|
|
||||||
|
### Required Fields
|
||||||
|
1. `BMS Version` must be "1.0"
|
||||||
|
2. `Map Name` must be non-empty string
|
||||||
|
3. `Grid Size` must match pattern "WxH" where W,H > 0
|
||||||
|
4. `Grid Unit` must contain "ft" (e.g., "5ft")
|
||||||
|
|
||||||
|
### Coordinate Validation
|
||||||
|
1. Coordinates must be within grid bounds
|
||||||
|
2. Rectangle `from` coordinates must be ≤ `to` coordinates
|
||||||
|
3. Room rectangles must not overlap (optional warning)
|
||||||
|
|
||||||
|
### Door Validation
|
||||||
|
1. Door must connect two existing rooms
|
||||||
|
2. Door position must be on room boundary
|
||||||
|
3. Hinge side must be consistent with door position
|
||||||
|
|
||||||
|
### Lighting Validation
|
||||||
|
1. Light position must be within a room
|
||||||
|
2. Bright radius ≤ dim radius
|
||||||
|
3. Color must be valid CSS color
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Start Simple**: Define rooms and connections first
|
||||||
|
2. **Be Specific**: Use exact coordinates, not "center of room"
|
||||||
|
3. **Consistent Naming**: R1, D1, O1, H1, L1, etc.
|
||||||
|
4. **Include DCs**: For all interactive elements
|
||||||
|
5. **Visual Notes**: Describe what players SEE
|
||||||
|
6. **Mechanical Notes**: Describe what players INTERACT WITH
|
||||||
|
7. **Layer Complexity**: Add hazards/objects after base layout
|
||||||
|
|
||||||
|
---
|
||||||
|
*Last Updated: March 19, 2026*
|
||||||
313
docs/IMPLEMENTATION_ROADMAP.md
Normal file
313
docs/IMPLEMENTATION_ROADMAP.md
Normal file
|
|
@ -0,0 +1,313 @@
|
||||||
|
# BMS BattleMap Generator - Implementation Roadmap
|
||||||
|
|
||||||
|
## Phase 1: Frontend Renderer MVP (2-3 weeks)
|
||||||
|
|
||||||
|
### Week 1: Core Foundation
|
||||||
|
|
||||||
|
#### **Days 1-2: Project Setup**
|
||||||
|
**Tasks:**
|
||||||
|
1. Initialize Git repository
|
||||||
|
2. Create Vite + React + TypeScript project
|
||||||
|
3. Install core dependencies:
|
||||||
|
- `konva react-konva` (Canvas rendering)
|
||||||
|
- `js-yaml` (YAML parsing)
|
||||||
|
- `zod` (Validation)
|
||||||
|
- `@monaco-editor/react` (Code editor)
|
||||||
|
- `tailwindcss postcss autoprefixer` (Styling)
|
||||||
|
4. Configure development environment
|
||||||
|
5. Set up TypeScript, ESLint, Prettier
|
||||||
|
|
||||||
|
**Deliverables:**
|
||||||
|
- ✅ Project repository initialized
|
||||||
|
- ✅ Development environment working
|
||||||
|
- ✅ Basic React app running
|
||||||
|
|
||||||
|
#### **Days 3-4: BMS Schema Implementation**
|
||||||
|
**Tasks:**
|
||||||
|
1. Create TypeScript interfaces for BMS 1.0
|
||||||
|
2. Implement Zod validation schemas
|
||||||
|
3. Create YAML parsing utilities
|
||||||
|
4. Add error handling and validation
|
||||||
|
5. Create test BMS files for development
|
||||||
|
|
||||||
|
**Deliverables:**
|
||||||
|
- ✅ Complete BMS TypeScript types
|
||||||
|
- ✅ Runtime validation with Zod
|
||||||
|
- ✅ YAML parser with error messages
|
||||||
|
- ✅ Sample BMS files for testing
|
||||||
|
|
||||||
|
#### **Days 5-7: Basic Rendering Engine**
|
||||||
|
**Tasks:**
|
||||||
|
1. Set up Konva.js canvas
|
||||||
|
2. Implement grid renderer
|
||||||
|
3. Define Paperly style system
|
||||||
|
4. Create room renderer (walls, floors)
|
||||||
|
5. Add basic UI layout (editor + preview)
|
||||||
|
|
||||||
|
**Deliverables:**
|
||||||
|
- ✅ Canvas displaying grid
|
||||||
|
- ✅ Rooms rendered as rectangles
|
||||||
|
- ✅ Paperly style applied
|
||||||
|
- ✅ Split editor/preview layout
|
||||||
|
|
||||||
|
### Week 2: Complete BMS Support
|
||||||
|
|
||||||
|
#### **Days 8-10: Element Rendering**
|
||||||
|
**Tasks:**
|
||||||
|
1. Implement door renderer
|
||||||
|
- Open/closed states
|
||||||
|
- Hinge side indicators
|
||||||
|
- Connection lines
|
||||||
|
2. Create object renderer
|
||||||
|
- Simple geometric icons
|
||||||
|
- Labels and tooltips
|
||||||
|
- State indicators
|
||||||
|
3. Build hazard renderer
|
||||||
|
- Visual patterns
|
||||||
|
- Color coding
|
||||||
|
- DC indicators
|
||||||
|
|
||||||
|
**Deliverables:**
|
||||||
|
- ✅ Doors render with correct states
|
||||||
|
- ✅ Objects display as icons
|
||||||
|
- ✅ Hazards show visual patterns
|
||||||
|
- ✅ Real-time updates on YAML changes
|
||||||
|
|
||||||
|
#### **Days 11-12: Advanced Features**
|
||||||
|
**Tasks:**
|
||||||
|
1. Implement lighting renderer
|
||||||
|
- Light radius visualization
|
||||||
|
- Bright/dim zones
|
||||||
|
- Glow effects
|
||||||
|
2. Create annotation renderer
|
||||||
|
- Text labels
|
||||||
|
- DM notes
|
||||||
|
- Connection arrows
|
||||||
|
3. Build export system
|
||||||
|
- PNG export (canvas to image)
|
||||||
|
- JSON export (serialized BMS)
|
||||||
|
- BMS YAML export
|
||||||
|
|
||||||
|
**Deliverables:**
|
||||||
|
- ✅ Lighting effects rendered
|
||||||
|
- ✅ Annotations displayed
|
||||||
|
- ✅ Export functionality working
|
||||||
|
- ✅ Complete BMS 1.0 support
|
||||||
|
|
||||||
|
#### **Day 13: UI Polish**
|
||||||
|
**Tasks:**
|
||||||
|
1. Refine UI components
|
||||||
|
2. Add error reporting
|
||||||
|
3. Implement zoom/pan controls
|
||||||
|
4. Add keyboard shortcuts
|
||||||
|
5. Improve user experience
|
||||||
|
|
||||||
|
**Deliverables:**
|
||||||
|
- ✅ Polished UI
|
||||||
|
- ✅ Error messages for invalid BMS
|
||||||
|
- ✅ Zoom/pan functionality
|
||||||
|
- ✅ Keyboard shortcuts
|
||||||
|
|
||||||
|
### Week 3: Testing & Deployment
|
||||||
|
|
||||||
|
#### **Days 14-15: Testing & Bug Fixes**
|
||||||
|
**Tasks:**
|
||||||
|
1. Test with sample BMS files
|
||||||
|
2. Fix rendering issues
|
||||||
|
3. Optimize performance
|
||||||
|
4. Test on different browsers
|
||||||
|
5. Create documentation
|
||||||
|
|
||||||
|
**Deliverables:**
|
||||||
|
- ✅ All sample BMS files render correctly
|
||||||
|
- ✅ Performance optimized for large maps
|
||||||
|
- ✅ Cross-browser compatibility
|
||||||
|
- ✅ User documentation
|
||||||
|
|
||||||
|
#### **Days 16-17: Alpha Deployment**
|
||||||
|
**Tasks:**
|
||||||
|
1. Build production version
|
||||||
|
2. Deploy to maps.bouncypixel.com
|
||||||
|
3. Set up basic analytics (optional)
|
||||||
|
4. Create alpha testing guide
|
||||||
|
5. Invite initial testers
|
||||||
|
|
||||||
|
**Deliverables:**
|
||||||
|
- ✅ Production build completed
|
||||||
|
- ✅ Deployed to maps.bouncypixel.com
|
||||||
|
- ✅ Alpha testing environment ready
|
||||||
|
- ✅ Testers invited and briefed
|
||||||
|
|
||||||
|
## Phase 2: Texture Pack System (3-4 weeks)
|
||||||
|
|
||||||
|
### **Week 1: Texture Pack Architecture**
|
||||||
|
1. Design texture pack file structure
|
||||||
|
2. Create style configuration format
|
||||||
|
3. Implement texture loading system
|
||||||
|
4. Add texture pack manager UI
|
||||||
|
|
||||||
|
### **Week 2: Texture Rendering**
|
||||||
|
1. Modify renderer to use textures
|
||||||
|
2. Implement texture tiling
|
||||||
|
3. Add texture blending options
|
||||||
|
4. Create texture preview system
|
||||||
|
|
||||||
|
### **Week 3: Pack Management**
|
||||||
|
1. Implement pack purchase/download
|
||||||
|
2. Add pack activation/deactivation
|
||||||
|
3. Create pack marketplace UI
|
||||||
|
4. Add user account integration
|
||||||
|
|
||||||
|
### **Week 4: Polish & Release**
|
||||||
|
1. Create default texture packs
|
||||||
|
2. Test texture rendering
|
||||||
|
3. Optimize texture loading
|
||||||
|
4. Release to production
|
||||||
|
|
||||||
|
## Phase 3: AI Integration (4-5 weeks)
|
||||||
|
|
||||||
|
### **Week 1: AI API Integration**
|
||||||
|
1. Set up OpenAI API integration
|
||||||
|
2. Create BMS generation prompts
|
||||||
|
3. Implement basic AI generation
|
||||||
|
4. Add API key management
|
||||||
|
|
||||||
|
### **Week 2: Chat Interface**
|
||||||
|
1. Design chat-based UI
|
||||||
|
2. Implement conversation history
|
||||||
|
3. Add context preservation
|
||||||
|
4. Create iterative editing workflow
|
||||||
|
|
||||||
|
### **Week 3: Advanced AI Features**
|
||||||
|
1. Implement schema modification
|
||||||
|
2. Add suggestion system
|
||||||
|
3. Create validation feedback
|
||||||
|
4. Implement rate limiting
|
||||||
|
|
||||||
|
### **Week 4: Monetization Integration**
|
||||||
|
1. Add subscription system
|
||||||
|
2. Implement API usage tracking
|
||||||
|
3. Create tiered feature access
|
||||||
|
4. Add payment processing
|
||||||
|
|
||||||
|
### **Week 5: Testing & Release**
|
||||||
|
1. Test AI generation quality
|
||||||
|
2. Optimize prompt engineering
|
||||||
|
3. Performance testing
|
||||||
|
4. Release to production
|
||||||
|
|
||||||
|
## Phase 4: VTT Export & Community Features (4-5 weeks)
|
||||||
|
|
||||||
|
### **Week 1: VTT Export Formats**
|
||||||
|
1. Implement FoundryVTT export
|
||||||
|
2. Add Roll20 compatibility
|
||||||
|
3. Create universal VTT format
|
||||||
|
4. Test with popular VTTs
|
||||||
|
|
||||||
|
### **Week 2: Community Features**
|
||||||
|
1. Add template sharing
|
||||||
|
2. Create user profiles
|
||||||
|
3. Implement rating system
|
||||||
|
4. Add search functionality
|
||||||
|
|
||||||
|
### **Week 3: Advanced Tools**
|
||||||
|
1. Add map editing tools
|
||||||
|
2. Implement undo/redo
|
||||||
|
3. Create layer management
|
||||||
|
4. Add measurement tools
|
||||||
|
|
||||||
|
### **Week 4: Performance & Scaling**
|
||||||
|
1. Optimize for large maps
|
||||||
|
2. Implement caching
|
||||||
|
3. Add CDN for assets
|
||||||
|
4. Scale infrastructure
|
||||||
|
|
||||||
|
### **Week 5: Polish & Release**
|
||||||
|
1. User feedback implementation
|
||||||
|
2. Bug fixes
|
||||||
|
3. Documentation updates
|
||||||
|
4. Production release
|
||||||
|
|
||||||
|
## Success Metrics
|
||||||
|
|
||||||
|
### Phase 1 (MVP)
|
||||||
|
- ✅ BMS 1.0 YAML parsing
|
||||||
|
- ✅ Complete rendering with Paperly style
|
||||||
|
- ✅ Real-time editor + preview
|
||||||
|
- ✅ PNG/JSON export
|
||||||
|
- ✅ Alpha testing with 5-10 users
|
||||||
|
- ✅ Positive feedback on usability
|
||||||
|
|
||||||
|
### Phase 2 (Texture Packs)
|
||||||
|
- ✅ Texture pack system working
|
||||||
|
- ✅ At least 3 quality texture packs
|
||||||
|
- ✅ Users can purchase/activate packs
|
||||||
|
- ✅ Texture rendering performs well
|
||||||
|
|
||||||
|
### Phase 3 (AI Integration)
|
||||||
|
- ✅ AI generates valid BMS schemas
|
||||||
|
- ✅ Chat interface intuitive
|
||||||
|
- ✅ Iterative editing works smoothly
|
||||||
|
- ✅ Subscription system functional
|
||||||
|
|
||||||
|
### Phase 4 (Complete Platform)
|
||||||
|
- ✅ VTT export works with major platforms
|
||||||
|
- ✅ Community templates shared
|
||||||
|
- ✅ Performance handles large maps
|
||||||
|
- ✅ Platform scales with users
|
||||||
|
|
||||||
|
## Risk Mitigation
|
||||||
|
|
||||||
|
### Technical Risks
|
||||||
|
1. **Canvas Performance**: Use Konva.js optimizations, implement viewport culling
|
||||||
|
2. **Large Map Rendering**: Implement level-of-detail, progressive rendering
|
||||||
|
3. **Browser Compatibility**: Focus on modern browsers, polyfill if needed
|
||||||
|
4. **YAML Parsing**: Robust error handling, helpful error messages
|
||||||
|
|
||||||
|
### Business Risks
|
||||||
|
1. **User Adoption**: Free tier lowers barrier, focus on useful core features
|
||||||
|
2. **Monetization**: Multiple revenue streams (packs, subscription, AI)
|
||||||
|
3. **Competition**: Unique BMS format, AI integration, community focus
|
||||||
|
4. **Technical Debt**: Clean architecture, modular design, regular refactoring
|
||||||
|
|
||||||
|
## Resource Requirements
|
||||||
|
|
||||||
|
### Development
|
||||||
|
- **Frontend Developer**: 3-4 months full-time (or equivalent)
|
||||||
|
- **Designer**: 1-2 months for UI/UX and texture packs
|
||||||
|
- **AI/Backend**: 1-2 months for AI integration (optional backend)
|
||||||
|
|
||||||
|
### Infrastructure
|
||||||
|
- **Hosting**: Static site hosting (Vercel, Netlify, self-hosted)
|
||||||
|
- **Storage**: CDN for texture packs
|
||||||
|
- **API**: Optional for AI features
|
||||||
|
- **Database**: Optional for user accounts/templates
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- **Alpha Testers**: 5-10 trusted users
|
||||||
|
- **Beta Testers**: 50-100 users
|
||||||
|
- **Production Testing**: Continuous user feedback
|
||||||
|
|
||||||
|
## Future Considerations
|
||||||
|
|
||||||
|
### Technical Debt
|
||||||
|
- Regular code reviews
|
||||||
|
- Comprehensive testing
|
||||||
|
- Documentation updates
|
||||||
|
- Performance monitoring
|
||||||
|
|
||||||
|
### Feature Backlog
|
||||||
|
1. 3D top-down view
|
||||||
|
2. Mobile app
|
||||||
|
3. Collaborative editing
|
||||||
|
4. Plugin system
|
||||||
|
5. Advanced generation algorithms
|
||||||
|
6. Integration with other TTRPG tools
|
||||||
|
7. Print-friendly formats
|
||||||
|
8. Custom asset import
|
||||||
|
9. Advanced lighting simulation
|
||||||
|
10. Sound effects integration
|
||||||
|
|
||||||
|
---
|
||||||
|
*Last Updated: March 19, 2026*
|
||||||
|
*Next Review: After Phase 1 Completion*
|
||||||
244
docs/PROJECT_PLAN.md
Normal file
244
docs/PROJECT_PLAN.md
Normal file
|
|
@ -0,0 +1,244 @@
|
||||||
|
# BMS BattleMap Generator - Project Plan
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
A web-based tool for rendering DnD/TTRPG battlemaps using the Battlemap Notation Schema (BMS) format.
|
||||||
|
|
||||||
|
**Primary Goal**: Create a frontend renderer that parses BMS YAML and renders battlemaps with a default "Paperly" style.
|
||||||
|
|
||||||
|
**Monetization Strategy**:
|
||||||
|
- **Free Tier**: Basic rendering with Paperly style
|
||||||
|
- **Paid Features**: Texture packs, AI integration (future)
|
||||||
|
- **Subscription**: Access to all texture packs + AI features
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
- **Framework**: React 19 + TypeScript
|
||||||
|
- **Build Tool**: Vite
|
||||||
|
- **Canvas**: Konva.js (via react-konva)
|
||||||
|
- **Validation**: Zod
|
||||||
|
- **YAML Parsing**: js-yaml
|
||||||
|
- **Editor**: Monaco Editor
|
||||||
|
- **Styling**: Tailwind CSS
|
||||||
|
|
||||||
|
### Optional Backend (Future)
|
||||||
|
- **Runtime**: .NET 8 Minimal API
|
||||||
|
- **Validation**: JSON Schema.NET
|
||||||
|
- **YAML**: YamlDotNet
|
||||||
|
- **AI**: OpenAI SDK
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
```
|
||||||
|
bms-forge/
|
||||||
|
├── public/
|
||||||
|
├── src/
|
||||||
|
│ ├── types/ # BMS TypeScript interfaces
|
||||||
|
│ ├── schema/ # Zod validation schemas
|
||||||
|
│ ├── parser/ # YAML parsing utilities
|
||||||
|
│ ├── renderer/ # Konva.js rendering engine
|
||||||
|
│ │ ├── layers/ # Individual layer renderers
|
||||||
|
│ │ └── styles/ # Paperly + future texture packs
|
||||||
|
│ ├── components/ # React components
|
||||||
|
│ ├── hooks/ # Custom React hooks
|
||||||
|
│ ├── utils/ # Helper functions
|
||||||
|
│ └── App.tsx
|
||||||
|
├── package.json
|
||||||
|
└── vite.config.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 1: Frontend Renderer MVP (2-3 weeks)
|
||||||
|
|
||||||
|
### Week 1: Core Foundation
|
||||||
|
**Days 1-2**: Project Setup
|
||||||
|
- Initialize repository with Vite + React + TypeScript
|
||||||
|
- Install core dependencies
|
||||||
|
- Configure development environment
|
||||||
|
|
||||||
|
**Days 3-4**: BMS Schema Implementation
|
||||||
|
- Complete TypeScript interfaces for BMS 1.0
|
||||||
|
- Zod validation schemas
|
||||||
|
- YAML parser with error handling
|
||||||
|
|
||||||
|
**Days 5-7**: Basic Rendering Engine
|
||||||
|
- Grid renderer
|
||||||
|
- Paperly style system
|
||||||
|
- Room rendering
|
||||||
|
|
||||||
|
### Week 2: Complete BMS Support
|
||||||
|
**Days 8-10**: Element Rendering
|
||||||
|
- Door renderer (open/closed states)
|
||||||
|
- Object renderer (simple geometric icons)
|
||||||
|
- Hazard renderer (visual patterns)
|
||||||
|
|
||||||
|
**Days 11-12**: Advanced Features
|
||||||
|
- Lighting renderer (radius visualization)
|
||||||
|
- Annotation renderer (text labels)
|
||||||
|
- Export system (PNG, JSON, BMS YAML)
|
||||||
|
|
||||||
|
### Week 3: Polish & Alpha Testing
|
||||||
|
- UI refinement
|
||||||
|
- Performance optimization
|
||||||
|
- Alpha testing with trusted users
|
||||||
|
- Bug fixes and improvements
|
||||||
|
|
||||||
|
## BMS Schema Implementation
|
||||||
|
|
||||||
|
### Core Types
|
||||||
|
```typescript
|
||||||
|
type Coordinate = [number, number]; // (x, y)
|
||||||
|
type Rectangle = { from: Coordinate; to: Coordinate };
|
||||||
|
|
||||||
|
interface BMSHeader {
|
||||||
|
bmsVersion: string;
|
||||||
|
mapName: string;
|
||||||
|
gridSize: { width: number; height: number };
|
||||||
|
gridUnit: string;
|
||||||
|
style: string;
|
||||||
|
lighting: string;
|
||||||
|
ambientSound?: string;
|
||||||
|
temperature?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BMSSchema extends BMSHeader {
|
||||||
|
rooms?: Room[];
|
||||||
|
doors?: Door[];
|
||||||
|
objects?: MapObject[];
|
||||||
|
hazards?: Hazard[];
|
||||||
|
lightingSources?: LightSource[];
|
||||||
|
connections?: Connection[];
|
||||||
|
annotations?: Annotation[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Paperly Style Definition
|
||||||
|
```typescript
|
||||||
|
const paperlyStyle = {
|
||||||
|
grid: { color: "#ccc", opacity: 0.3, lineWidth: 1 },
|
||||||
|
rooms: { fill: "#f8f8f8", stroke: "#666", strokeWidth: 2 },
|
||||||
|
walls: { color: "#333", thickness: 3 },
|
||||||
|
doors: {
|
||||||
|
open: { fill: "#8BC34A", stroke: "#689F38" },
|
||||||
|
closed: { fill: "#795548", stroke: "#5D4037" }
|
||||||
|
},
|
||||||
|
objects: { color: "#666", size: 20 },
|
||||||
|
hazards: { color: "#f44336", pattern: "diagonal" },
|
||||||
|
lighting: { glow: "#FFEB3B", opacity: 0.3 }
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rendering Engine Architecture
|
||||||
|
|
||||||
|
### Layered Rendering System
|
||||||
|
1. **Layer 7**: Annotations (text, labels)
|
||||||
|
2. **Layer 6**: Lighting effects (glows, shadows)
|
||||||
|
3. **Layer 5**: Objects & Hazards (icons, patterns)
|
||||||
|
4. **Layer 4**: Doors (with state indicators)
|
||||||
|
5. **Layer 3**: Room interiors (floor textures, features)
|
||||||
|
6. **Layer 2**: Walls (with material styles)
|
||||||
|
7. **Layer 1**: Grid & Background
|
||||||
|
|
||||||
|
### Renderer Class Structure
|
||||||
|
```typescript
|
||||||
|
class PaperlyRenderer {
|
||||||
|
private stage: Konva.Stage;
|
||||||
|
private layers: Map<string, Konva.Layer>;
|
||||||
|
|
||||||
|
render(schema: BMSSchema): void {
|
||||||
|
this.setupCanvas(schema.gridSize);
|
||||||
|
this.renderGrid();
|
||||||
|
this.renderRooms(schema.rooms);
|
||||||
|
this.renderDoors(schema.doors);
|
||||||
|
// ... other elements
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## UI Component Structure
|
||||||
|
|
||||||
|
### Main Layout
|
||||||
|
```
|
||||||
|
Header
|
||||||
|
└── App Title, Version, Links
|
||||||
|
|
||||||
|
Main Content (flex)
|
||||||
|
├── EditorPanel (Monaco Editor with YAML)
|
||||||
|
├── PreviewPanel (Konva Canvas)
|
||||||
|
└── ToolsPanel (Export buttons, options)
|
||||||
|
|
||||||
|
StatusBar
|
||||||
|
└── Grid info, errors, zoom level
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Components
|
||||||
|
1. **`EditorPanel`**: Monaco editor with YAML syntax highlighting
|
||||||
|
2. **`PreviewPanel`**: Konva canvas with rendered map
|
||||||
|
3. **`ToolsPanel`**: Export buttons, style options, validation status
|
||||||
|
4. **`Header`**: App title, version, links
|
||||||
|
5. **`StatusBar`**: Grid info, errors, zoom level
|
||||||
|
|
||||||
|
## Future Features
|
||||||
|
|
||||||
|
### Texture Pack System
|
||||||
|
- Individual texture pack purchases ($4.99 each)
|
||||||
|
- Subscription access to all packs
|
||||||
|
- Pack structure:
|
||||||
|
```
|
||||||
|
texture-packs/
|
||||||
|
├── medieval-stone/
|
||||||
|
│ ├── pack.json
|
||||||
|
│ ├── walls/
|
||||||
|
│ ├── floors/
|
||||||
|
│ └── objects/
|
||||||
|
```
|
||||||
|
|
||||||
|
### AI Integration
|
||||||
|
- **Free tier**: Bring-your-own-API key
|
||||||
|
- **Paid tier**: Managed API with rate limits
|
||||||
|
- **Chat-based iteration**: Natural language to modify BMS schemas
|
||||||
|
|
||||||
|
### VTT Export
|
||||||
|
- FoundryVTT scene format
|
||||||
|
- Roll20 compatibility
|
||||||
|
- Universal VTT format
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### Alpha Testing
|
||||||
|
- **URL**: maps.bouncypixel.com
|
||||||
|
- **Build**: Vite production build
|
||||||
|
- **Hosting**: Self-hosted subdomain
|
||||||
|
- **Testing**: 5-10 trusted alpha testers
|
||||||
|
|
||||||
|
### Production Considerations
|
||||||
|
- **Custom Domain**: bms-forge.com or similar
|
||||||
|
- **CDN**: For texture packs and assets
|
||||||
|
- **Analytics**: Basic usage tracking (optional)
|
||||||
|
- **CI/CD**: Automated build and deployment
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
### MVP Completion
|
||||||
|
- [ ] Parse and validate BMS 1.0 YAML
|
||||||
|
- [ ] Render all BMS elements with Paperly style
|
||||||
|
- [ ] Real-time editor + preview
|
||||||
|
- [ ] Export to PNG and JSON
|
||||||
|
- [ ] Deploy to maps.bouncypixel.com
|
||||||
|
- [ ] Gather feedback from alpha testers
|
||||||
|
|
||||||
|
### Phase 2 Goals
|
||||||
|
- [ ] Texture pack system
|
||||||
|
- [ ] AI integration
|
||||||
|
- [ ] VTT export functionality
|
||||||
|
- [ ] Community template sharing
|
||||||
|
- [ ] Monetization system
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- **Version Control**: Private Forgejo at git.bouncypixel.com
|
||||||
|
- **Analytics**: Optional future feature
|
||||||
|
- **Community**: Discord for user feedback
|
||||||
|
- **Browser Support**: Modern browsers only for V1
|
||||||
|
- **Mobile**: Desktop-focused initially
|
||||||
|
|
||||||
|
---
|
||||||
|
*Last Updated: March 19, 2026*
|
||||||
419
docs/TECHNICAL_ARCHITECTURE.md
Normal file
419
docs/TECHNICAL_ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,419 @@
|
||||||
|
# BMS BattleMap Generator - Technical Architecture
|
||||||
|
|
||||||
|
## System Overview
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ Frontend Application │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ Editor Interface Preview Canvas Tools Panel │
|
||||||
|
│ (Monaco Editor) (Konva.js Canvas) (Export/Options) │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ State Management │
|
||||||
|
│ (React Hooks/Context) │
|
||||||
|
├─────────────────────────────────────────────────────────────┤
|
||||||
|
│ YAML Parser │ Schema Validator │ Renderer Engine │
|
||||||
|
│ (js-yaml) │ (Zod) │ (Konva.js Layers) │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Component Architecture
|
||||||
|
|
||||||
|
### 1. BMS Schema Module (`src/schema/`)
|
||||||
|
```
|
||||||
|
schema/
|
||||||
|
├── types.ts # TypeScript interfaces
|
||||||
|
├── validators.ts # Zod validation schemas
|
||||||
|
├── parsers.ts # Coordinate/range parsing
|
||||||
|
├── transformers.ts # Data transformation
|
||||||
|
└── index.ts # Public API
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Parser Module (`src/parser/`)
|
||||||
|
```
|
||||||
|
parser/
|
||||||
|
├── yaml-parser.ts # BMS YAML parsing
|
||||||
|
├── coordinate-parser.ts # Grid coordinate parsing
|
||||||
|
├── validation.ts # Schema validation logic
|
||||||
|
├── errors.ts # Error types and messages
|
||||||
|
└── index.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Renderer Module (`src/renderer/`)
|
||||||
|
```
|
||||||
|
renderer/
|
||||||
|
├── base-renderer.ts # Abstract base class
|
||||||
|
├── paperly-renderer.ts # Paperly style implementation
|
||||||
|
├── texture-renderer.ts # Future: texture pack rendering
|
||||||
|
├── layers/ # Individual layer renderers
|
||||||
|
│ ├── grid-layer.ts
|
||||||
|
│ ├── room-layer.ts
|
||||||
|
│ ├── door-layer.ts
|
||||||
|
│ ├── object-layer.ts
|
||||||
|
│ ├── hazard-layer.ts
|
||||||
|
│ ├── lighting-layer.ts
|
||||||
|
│ └── annotation-layer.ts
|
||||||
|
├── styles/ # Style definitions
|
||||||
|
│ ├── paperly-style.ts
|
||||||
|
│ └── texture-styles.ts # Future
|
||||||
|
└── utils/ # Rendering utilities
|
||||||
|
├── geometry.ts
|
||||||
|
├── colors.ts
|
||||||
|
└── textures.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. UI Components (`src/components/`)
|
||||||
|
```
|
||||||
|
components/
|
||||||
|
├── Editor/
|
||||||
|
│ ├── YAMLEditor.tsx # Monaco editor wrapper
|
||||||
|
│ └── EditorPanel.tsx # Editor with error display
|
||||||
|
├── Preview/
|
||||||
|
│ ├── MapCanvas.tsx # Konva canvas wrapper
|
||||||
|
│ └── PreviewPanel.tsx # Preview with controls
|
||||||
|
├── Tools/
|
||||||
|
│ ├── ExportMenu.tsx # Export options
|
||||||
|
│ ├── StylePicker.tsx # Style selection
|
||||||
|
│ └── ValidationPanel.tsx # Validation status
|
||||||
|
├── Layout/
|
||||||
|
│ ├── Header.tsx
|
||||||
|
│ ├── Sidebar.tsx
|
||||||
|
│ └── StatusBar.tsx
|
||||||
|
└── Common/
|
||||||
|
├── ErrorDisplay.tsx
|
||||||
|
├── LoadingSpinner.tsx
|
||||||
|
└── Tooltip.tsx
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. State Management (`src/hooks/`, `src/context/`)
|
||||||
|
```
|
||||||
|
hooks/
|
||||||
|
├── useBMS.ts # BMS schema state
|
||||||
|
├── useRenderer.ts # Renderer instance
|
||||||
|
├── useExport.ts # Export functionality
|
||||||
|
└── useUndoRedo.ts # Undo/redo history
|
||||||
|
|
||||||
|
context/
|
||||||
|
├── AppContext.tsx # Global app state
|
||||||
|
└── ThemeContext.tsx # Theme/stylesheet
|
||||||
|
```
|
||||||
|
|
||||||
|
## Data Flow
|
||||||
|
|
||||||
|
### 1. Parsing Pipeline
|
||||||
|
```
|
||||||
|
User Input (YAML)
|
||||||
|
↓
|
||||||
|
YAML Parser (js-yaml)
|
||||||
|
↓
|
||||||
|
Schema Validator (Zod)
|
||||||
|
↓
|
||||||
|
BMSSchema Object
|
||||||
|
↓
|
||||||
|
Renderer Engine
|
||||||
|
↓
|
||||||
|
Canvas Output
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Rendering Pipeline
|
||||||
|
```
|
||||||
|
BMSSchema
|
||||||
|
↓
|
||||||
|
Setup Canvas (grid size, scale)
|
||||||
|
↓
|
||||||
|
Render Layers (in order):
|
||||||
|
1. Grid Layer
|
||||||
|
2. Room Layer (walls, floors)
|
||||||
|
3. Door Layer
|
||||||
|
4. Object Layer
|
||||||
|
5. Hazard Layer
|
||||||
|
6. Lighting Layer
|
||||||
|
7. Annotation Layer
|
||||||
|
↓
|
||||||
|
Canvas Output
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Export Pipeline
|
||||||
|
```
|
||||||
|
Canvas State
|
||||||
|
↓
|
||||||
|
Export Format Selection
|
||||||
|
↓
|
||||||
|
Format-Specific Exporter:
|
||||||
|
- PNG: canvas.toDataURL()
|
||||||
|
- JSON: JSON.stringify(BMSSchema)
|
||||||
|
- BMS: serializeBMSToYAML()
|
||||||
|
↓
|
||||||
|
File Download
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Technical Decisions
|
||||||
|
|
||||||
|
### 1. Canvas Library: Konva.js
|
||||||
|
**Why Konva.js over alternatives:**
|
||||||
|
- **React Integration**: react-konva provides React component wrappers
|
||||||
|
- **Performance**: Hardware acceleration, efficient rendering
|
||||||
|
- **Features**: Layers, events, transforms, filters
|
||||||
|
- **Size**: Smaller than PIXI.js, more focused than raw Canvas API
|
||||||
|
- **Maintenance**: Active development, good documentation
|
||||||
|
|
||||||
|
### 2. Validation: Zod
|
||||||
|
**Why Zod over alternatives:**
|
||||||
|
- **TypeScript Integration**: Automatic type inference
|
||||||
|
- **Runtime Safety**: Comprehensive validation at runtime
|
||||||
|
- **Error Messages**: Customizable error messages
|
||||||
|
- **Size**: Small bundle size
|
||||||
|
- **Schema Composition**: Easy to compose and extend schemas
|
||||||
|
|
||||||
|
### 3. YAML Parsing: js-yaml
|
||||||
|
**Why js-yaml:**
|
||||||
|
- **Browser Support**: Works in browser environments
|
||||||
|
- **Safety**: Secure parsing options
|
||||||
|
- **Performance**: Fast and efficient
|
||||||
|
- **Features**: Full YAML 1.2 support
|
||||||
|
|
||||||
|
### 4. State Management: React Hooks
|
||||||
|
**Why React Hooks over Redux/MobX:**
|
||||||
|
- **Simplicity**: Less boilerplate for MVP
|
||||||
|
- **Performance**: Optimized re-renders with useMemo/useCallback
|
||||||
|
- **Scalability**: Can migrate to Context or Zustand if needed
|
||||||
|
- **Learning Curve**: Familiar to React developers
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
### 1. Rendering Optimization
|
||||||
|
```typescript
|
||||||
|
// Use Konva.js optimizations
|
||||||
|
const optimizedRender = () => {
|
||||||
|
// Batch updates
|
||||||
|
stage.batchDraw();
|
||||||
|
|
||||||
|
// Use caching for static elements
|
||||||
|
shape.cache();
|
||||||
|
|
||||||
|
// Implement viewport culling
|
||||||
|
if (isInViewport(element)) {
|
||||||
|
renderElement(element);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Memory Management
|
||||||
|
```typescript
|
||||||
|
// Clean up resources
|
||||||
|
useEffect(() => {
|
||||||
|
const renderer = new PaperlyRenderer();
|
||||||
|
return () => {
|
||||||
|
renderer.destroy(); // Clean up Konva objects
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Large Map Handling
|
||||||
|
```typescript
|
||||||
|
// Implement level of detail
|
||||||
|
const getDetailLevel = (zoom: number): DetailLevel => {
|
||||||
|
if (zoom < 0.5) return 'low';
|
||||||
|
if (zoom < 1.0) return 'medium';
|
||||||
|
return 'high';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Progressive rendering
|
||||||
|
const renderProgressive = async (schema: BMSSchema) => {
|
||||||
|
// Render grid first
|
||||||
|
renderGrid();
|
||||||
|
|
||||||
|
// Render rooms
|
||||||
|
await renderRooms(schema.rooms);
|
||||||
|
|
||||||
|
// Render details progressively
|
||||||
|
requestIdleCallback(() => {
|
||||||
|
renderDoors(schema.doors);
|
||||||
|
renderObjects(schema.objects);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
### 1. YAML Parsing Security
|
||||||
|
```typescript
|
||||||
|
import { load } from 'js-yaml';
|
||||||
|
|
||||||
|
// Safe YAML parsing
|
||||||
|
const parseBMSYAML = (yaml: string): BMSSchema => {
|
||||||
|
try {
|
||||||
|
// Use safeLoad to prevent code execution
|
||||||
|
const parsed = load(yaml, {
|
||||||
|
schema: yaml.DEFAULT_SAFE_SCHEMA,
|
||||||
|
onWarning: (warning) => console.warn(warning)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Validate structure
|
||||||
|
return bmsSchema.parse(parsed);
|
||||||
|
} catch (error) {
|
||||||
|
throw new BMSValidationError('Invalid BMS YAML', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. File Export Security
|
||||||
|
```typescript
|
||||||
|
// Safe file naming
|
||||||
|
const sanitizeFilename = (name: string): string => {
|
||||||
|
return name.replace(/[^a-z0-9-_.]/gi, '_');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Content security for downloads
|
||||||
|
const downloadFile = (content: string, filename: string) => {
|
||||||
|
const blob = new Blob([content], { type: 'application/octet-stream' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
// Use safe download pattern
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = sanitizeFilename(filename);
|
||||||
|
a.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing Strategy
|
||||||
|
|
||||||
|
### 1. Unit Tests
|
||||||
|
```typescript
|
||||||
|
// Test coordinate parsing
|
||||||
|
describe('parseCoordinate', () => {
|
||||||
|
it('should parse valid coordinates', () => {
|
||||||
|
expect(parseCoordinate('(5,10)')).toEqual([5, 10]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for invalid format', () => {
|
||||||
|
expect(() => parseCoordinate('5,10')).toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Integration Tests
|
||||||
|
```typescript
|
||||||
|
// Test full parsing pipeline
|
||||||
|
describe('BMS Parser Integration', () => {
|
||||||
|
it('should parse and validate complete BMS', () => {
|
||||||
|
const yaml = sampleBMSYAML;
|
||||||
|
const schema = parseBMSYAML(yaml);
|
||||||
|
expect(schema.mapName).toBe('Guard Room');
|
||||||
|
expect(schema.rooms).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Visual Regression Tests
|
||||||
|
```typescript
|
||||||
|
// Compare rendered output
|
||||||
|
describe('Renderer Visual Tests', () => {
|
||||||
|
it('should render rooms correctly', async () => {
|
||||||
|
const schema = createTestSchema();
|
||||||
|
const renderer = new PaperlyRenderer();
|
||||||
|
const image = await renderer.renderToImage(schema);
|
||||||
|
|
||||||
|
// Compare with baseline
|
||||||
|
expect(image).toMatchImageSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deployment Architecture
|
||||||
|
|
||||||
|
### 1. Development Environment
|
||||||
|
```
|
||||||
|
Local Machine → Vite Dev Server → Browser
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Alpha Deployment
|
||||||
|
```
|
||||||
|
Git Repository → Build (Vite) → Static Files → maps.bouncypixel.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Future Production Deployment
|
||||||
|
```
|
||||||
|
GitHub Actions → Build & Test → CDN (Vercel/Netlify) → Custom Domain
|
||||||
|
↘ Texture Packs → Cloud Storage (S3/Cloudflare)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Scalability Considerations
|
||||||
|
|
||||||
|
### 1. Frontend Scaling
|
||||||
|
- **Code Splitting**: Lazy load components
|
||||||
|
- **Bundle Optimization**: Tree shaking, compression
|
||||||
|
- **CDN**: Static assets via CDN
|
||||||
|
|
||||||
|
### 2. Rendering Scaling
|
||||||
|
- **Virtualization**: Only render visible area
|
||||||
|
- **Web Workers**: Offload heavy computation
|
||||||
|
- **Caching**: Cache rendered elements
|
||||||
|
|
||||||
|
### 3. Data Scaling
|
||||||
|
- **IndexedDB**: Local storage for large maps
|
||||||
|
- **Compression**: Compress BMS data
|
||||||
|
- **Streaming**: Progressive loading
|
||||||
|
|
||||||
|
## Monitoring & Analytics
|
||||||
|
|
||||||
|
### 1. Performance Monitoring
|
||||||
|
```typescript
|
||||||
|
// Track rendering performance
|
||||||
|
const measureRender = (schema: BMSSchema) => {
|
||||||
|
performance.mark('render-start');
|
||||||
|
renderer.render(schema);
|
||||||
|
performance.mark('render-end');
|
||||||
|
|
||||||
|
const measure = performance.measure('render', 'render-start', 'render-end');
|
||||||
|
console.log(`Render time: ${measure.duration}ms`);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Error Tracking
|
||||||
|
```typescript
|
||||||
|
// Centralized error handling
|
||||||
|
class ErrorTracker {
|
||||||
|
static track(error: Error, context?: any) {
|
||||||
|
console.error('BMS Error:', error, context);
|
||||||
|
// Send to error tracking service (future)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Usage Analytics (Optional)
|
||||||
|
```typescript
|
||||||
|
// Basic usage tracking
|
||||||
|
const trackEvent = (event: string, data?: any) => {
|
||||||
|
if (process.env.NODE_ENV === 'production') {
|
||||||
|
// Send to analytics service
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Future Technical Considerations
|
||||||
|
|
||||||
|
### 1. Plugin System
|
||||||
|
```typescript
|
||||||
|
interface BMSPlugin {
|
||||||
|
name: string;
|
||||||
|
version: string;
|
||||||
|
init: (app: BMSApp) => void;
|
||||||
|
render?: (context: RenderContext) => void;
|
||||||
|
export?: (schema: BMSSchema) => any;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Collaborative Features
|
||||||
|
- **WebSocket**: Real-time collaboration
|
||||||
|
- **Conflict Resolution**: Operational transforms
|
||||||
|
- **Presence**: User cursor/selection
|
||||||
|
|
||||||
|
### 3. Offline Support
|
||||||
|
- **Service Workers**: Offline functionality
|
||||||
|
- **Local Storage**: Save work locally
|
||||||
|
- **Sync**: Background synchronization
|
||||||
|
|
||||||
|
---
|
||||||
|
*Last Updated: March 19, 2026*
|
||||||
28
eslint.config.js
Normal file
28
eslint.config.js
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import js from '@eslint/js'
|
||||||
|
import globals from 'globals'
|
||||||
|
import reactHooks from 'eslint-plugin-react-hooks'
|
||||||
|
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||||
|
import tseslint from 'typescript-eslint'
|
||||||
|
|
||||||
|
export default tseslint.config(
|
||||||
|
{ ignores: ['dist'] },
|
||||||
|
{
|
||||||
|
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||||
|
files: ['**/*.{ts,tsx}'],
|
||||||
|
languageOptions: {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
globals: globals.browser,
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
'react-hooks': reactHooks,
|
||||||
|
'react-refresh': reactRefresh,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
...reactHooks.configs.recommended.rules,
|
||||||
|
'react-refresh/only-export-components': [
|
||||||
|
'warn',
|
||||||
|
{ allowConstantExport: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
14
index.html
Normal file
14
index.html
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>BMS Forge - BattleMap Generator</title>
|
||||||
|
<meta name="description" content="Render and edit DnD/TTRPG battlemaps using the Battlemap Notation Schema (BMS) format">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4377
package-lock.json
generated
Normal file
4377
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
39
package.json
Normal file
39
package.json
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"name": "bms-forge",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.1.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc && vite build",
|
||||||
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"type-check": "tsc --noEmit"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@monaco-editor/react": "^4.6.0",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"konva": "^9.3.16",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0",
|
||||||
|
"react-konva": "^18.2.10",
|
||||||
|
"zod": "^3.23.8"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/js-yaml": "^4.0.9",
|
||||||
|
"@types/node": "^22.10.6",
|
||||||
|
"@types/react": "^19.0.7",
|
||||||
|
"@types/react-dom": "^19.0.3",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^8.26.1",
|
||||||
|
"@typescript-eslint/parser": "^8.26.1",
|
||||||
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
|
"autoprefixer": "^10.4.20",
|
||||||
|
"eslint": "^9.17.0",
|
||||||
|
"eslint-plugin-react-hooks": "^5.1.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.18",
|
||||||
|
"postcss": "^8.5.3",
|
||||||
|
"tailwindcss": "^3.4.1",
|
||||||
|
"typescript": "^5.7.3",
|
||||||
|
"vite": "^6.0.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
3
public/vite.svg
Normal file
3
public/vite.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
|
<path fill="currentColor" d="M8 0l6.5 4v8L8 16l-6.5-4V4z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 152 B |
70
src/App.tsx
Normal file
70
src/App.tsx
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-gray-900 text-gray-100">
|
||||||
|
<header className="border-b border-gray-800 p-4">
|
||||||
|
<div className="container mx-auto">
|
||||||
|
<h1 className="text-2xl font-bold">BMS Forge</h1>
|
||||||
|
<p className="text-gray-400">BattleMap Notation Schema Renderer</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main className="container mx-auto p-4">
|
||||||
|
<div className="rounded-lg border border-gray-800 bg-gray-800/50 p-8 text-center">
|
||||||
|
<h2 className="text-xl font-semibold mb-4">🚧 Under Construction</h2>
|
||||||
|
<p className="text-gray-300 mb-4">
|
||||||
|
The BMS Forge project is being initialized. Check back soon for the complete battlemap rendering tool.
|
||||||
|
</p>
|
||||||
|
<div className="inline-flex items-center gap-2 rounded-lg bg-gray-700 px-4 py-2 text-sm">
|
||||||
|
<div className="h-2 w-2 rounded-full bg-green-500 animate-pulse"></div>
|
||||||
|
<span>Initializing project...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8 grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
|
<div className="rounded-lg border border-gray-800 p-6">
|
||||||
|
<h3 className="font-semibold mb-2">✨ Features Coming Soon</h3>
|
||||||
|
<ul className="text-gray-300 space-y-1 text-sm">
|
||||||
|
<li>• BMS YAML parsing and validation</li>
|
||||||
|
<li>• Real-time battlemap rendering</li>
|
||||||
|
<li>• "Paperly" style default theme</li>
|
||||||
|
<li>• Export to PNG and JSON</li>
|
||||||
|
<li>• Texture pack system (future)</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="rounded-lg border border-gray-800 p-6">
|
||||||
|
<h3 className="font-semibold mb-2">📋 Project Status</h3>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<div>
|
||||||
|
<div className="flex justify-between text-sm mb-1">
|
||||||
|
<span>Project Setup</span>
|
||||||
|
<span className="text-green-400">Complete</span>
|
||||||
|
</div>
|
||||||
|
<div className="h-2 bg-gray-700 rounded-full overflow-hidden">
|
||||||
|
<div className="h-full w-full bg-green-500"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="flex justify-between text-sm mb-1">
|
||||||
|
<span>BMS Schema Implementation</span>
|
||||||
|
<span className="text-yellow-400">Next</span>
|
||||||
|
</div>
|
||||||
|
<div className="h-2 bg-gray-700 rounded-full overflow-hidden">
|
||||||
|
<div className="h-full w-1/4 bg-yellow-500"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer className="border-t border-gray-800 p-4 mt-8">
|
||||||
|
<div className="container mx-auto text-center text-gray-500 text-sm">
|
||||||
|
<p>BMS Forge v0.1.0 • Built with React + TypeScript + Konva.js</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App
|
||||||
31
src/index.css
Normal file
31
src/index.css
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
:root {
|
||||||
|
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
color-scheme: light dark;
|
||||||
|
color: rgba(255, 255, 255, 0.87);
|
||||||
|
background-color: #242424;
|
||||||
|
|
||||||
|
font-synthesis: none;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
min-width: 320px;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
color: #213547;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/main.tsx
Normal file
10
src/main.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { StrictMode } from 'react'
|
||||||
|
import { createRoot } from 'react-dom/client'
|
||||||
|
import App from './App.tsx'
|
||||||
|
import './index.css'
|
||||||
|
|
||||||
|
createRoot(document.getElementById('root')!).render(
|
||||||
|
<StrictMode>
|
||||||
|
<App />
|
||||||
|
</StrictMode>,
|
||||||
|
)
|
||||||
11
tailwind.config.js
Normal file
11
tailwind.config.js
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
export default {
|
||||||
|
content: [
|
||||||
|
"./index.html",
|
||||||
|
"./src/**/*.{js,ts,jsx,tsx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
25
tsconfig.json
Normal file
25
tsconfig.json
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
||||||
11
tsconfig.node.json
Normal file
11
tsconfig.node.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
20
vite.config.ts
Normal file
20
vite.config.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': path.resolve(__dirname, './src'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
port: 3000,
|
||||||
|
open: true,
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: 'dist',
|
||||||
|
sourcemap: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
Loading…
Add table
Reference in a new issue