Skip to main content

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-core and (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-server without modification

faerals-client

  • Bevy application: rendering, UI, input, audio, camera, tilemap
  • Calls into faerals-core for all game logic
  • Handles local SQLite persistence (MVP) and future server sync (Phase 3)

The one hard rule

faerals-core must never import bevy or 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-shared first, then both dependents
  • Game logic: unit tests in faerals-core
  • No hardcoded game data in source files