Architecture
Cargo workspace monorepo
faerals/
├── crates/
│ ├── faerals-core/ # Pure Rust: game logic, ecosystem, combat
│ ├── faerals-shared/ # Shared types: species, zones, climate, events
│ └── faerals-client/ # Bevy app: rendering, UI, input, audio
├── assets/
│ └── data/
│ └── species/ # Species definitions (TOML/RON files, not hardcoded)
├── wiki/ # Docusaurus documentation
└── Cargo.toml # Workspace root
faerals-server/ will be added in Phase 3.
Crate responsibilities
faerals-shared
- Serialisable data types only:
Species,Zone,Biome,Climate,EcologicalEvent, etc. - No Bevy. No game logic. Pure data that can cross the client/server boundary.
- Shared between
faerals-coreand (eventually)faerals-server.
faerals-core
- All game logic: ecosystem simulation, combat resolution, ability system, player state
- Must never depend on Bevy — this is a hard rule
- Unit-testable in isolation (cargo test)
- Will be reused by
faerals-serverwithout modification
faerals-client
- Bevy application: rendering, UI, input, audio, camera, tilemap
- Calls into
faerals-corefor all game logic - Handles local SQLite persistence (MVP) and future server sync (Phase 3)
The one hard rule
faerals-coremust never importbevyor any Bevy crate.
If game logic needs to touch Bevy systems, the logic belongs in faerals-client as a thin adapter, not in faerals-core. This keeps the simulation testable and portable.
Data files
Species, zone, and ability data lives in assets/data/ as TOML or RON files — never hardcoded. This means:
- Contributors can add content without touching Rust code
- Balance changes are data edits, not code changes
- The game can theoretically hot-reload data files during development
Collaboration conventions
- New features: one PR per feature, docs in the same PR
- Breaking changes to shared types: update
faerals-sharedfirst, then both dependents - Game logic: unit tests in
faerals-core - No hardcoded game data in source files