Template Structure Contract

This document defines the expected folder structure and contracts for a game integrating the Genius Engine. Strict adherence allows platform tooling and Genies to reliably parse and update your codebase.

1. Expected Structure

A typical Genius-powered game (funday/games/<game-id>/) MUST adhere to the following architecture:

games/<game-id>/
├── funday-plugin.json      # Core manifest + Genius metadata
├── README.md               # Quickstart and local dev notes
├── client/                 # Svelte 5 / Threlte Application
│   ├── src/
│   │   ├── components/     # Dumb UI, bound to unifiedGameState
│   │   ├── state/          # game-mode.svelte.ts, unifiedGameState definitions
│   │   ├── bridge/         # FundayBridge initialization and hooks
│   │   └── lib/            # Shared logic and utilities
├── server/                 # Nakama Go Logic
│   ├── match_handler.go    # Authoritative match loop
│   ├── rpc_genie.go        # genie_ingest_state, genie_inject_event
│   └── bot/                # Server-side AI logic
└── docs/                   # Genius Documentation Pack
    ├── fun-stack.md        # The instantiated design stack
    ├── perspectives.md     # Accessibility and UX lenses
    └── audits/             # Deep Roast reports

2. Boundaries

  • The Svelte Boundary: UI components inside client/src/components/ must be utterly ignorant of network status. They map properties purely from unifiedGameState.
  • The Server Boundary: The server/ logic must not trust the client. All actions must be validated, and hidden state must be scrubbed before broadcast.
  • The Docs Boundary: docs/ is the single source of truth for the game’s intent. Code changes should ideally be preceded by updates to the Fun Stack or Perspectives.

3. Acceptance & Verification

  • Criteria: The repository physically matches the logical contract.
    • Verify: Running tree games/<game-id> matches the expected folders, and funday-plugin.json accurately points to docs/fun-stack.md.

4. Rationale & Anti-Patterns

Why this specific structure?

The structure forces a decoupled game model. By placing UI components inside client/src/components/ and the network layer in client/src/bridge/ or client/src/nakama/, the visual representation can be mocked easily in isolation.

Common Anti-Patterns

  • The God Component: A single Game.svelte file that imports Nakama, handles user input, sets state, and renders the WebGL canvas. Why it fails: It cannot be simulated in local mode easily.
  • Hidden State in Components: Storing a player’s hp as let hp = $state(100) directly inside a PlayerHUD.svelte component. Why it fails: A Genie observer cannot read this state since it is not bound to unifiedGameState.
  • Skipping the Docs Directory: Failing to maintain docs/fun-stack.md alongside code updates. Why it fails: The codebase drifts from the design intent, making AI-driven audits and cross-team communication significantly harder.

5. Maintenance Best Practices

  1. Keep the funday-plugin.json up to date with any changes to the entryPoint or requested leaderboards.
  2. Continuously integrate Deep Roast feedback into the docs/audits/ folder.
  3. Review the perspectives.md after every major feature addition to ensure no UX regressions.

6. Directory Naming Conventions

To maintain a predictable workspace, ensure that nested directories also follow strict lower-kebab-case naming.

  • components/: Pure visual Svelte components. No complex state or network logic.
  • bridge/: Logic that explicitly wraps or interfaces with FundayBridge.
  • nakama/: Client-side Nakama RPC calls, match state parsing, and networking glue.
  • bot/: The offline AI or practice dummy logic, mimicking real player payloads.

Any deviation from this structure makes it significantly harder for automation to locate components, increasing the onboarding friction for new developers.

Ask Docs

AI assistant to help answer questions about the documentation. Answers are read-only and cite docs/source.

Hi! How can I help you with the documentation today? Answers are read-only and cite docs/source.

Ctrl+Enter to send