diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..5c2459b --- /dev/null +++ b/.env.example @@ -0,0 +1,35 @@ +# Space-Game Environment Configuration Example +# Copy this file to .env.local and fill in your actual values +# NEVER commit .env.local to version control + +# ============================================================================== +# SpacetimeDB Configuration +# ============================================================================== +# Primary variables (used by Rust backend) +SPACETIMEDB_DB_NAME=void-nav-dev +SPACETIMEDB_HOST=http://127.0.0.1:3000 + +# Frontend variables (Vite apps) +VITE_SPACETIMEDB_DB_NAME=void-nav-dev +VITE_SPACETIMEDB_HOST=http://127.0.0.1:3000 + +# ============================================================================== +# Better Auth Configuration +# ============================================================================== +# Generate a secure random secret for production: +# openssl rand -base64 32 +BETTER_AUTH_SECRET=your-secret-here-generate-with-openssl-rand-base64-32 +BETTER_AUTH_URL=http://localhost:4000 + +# ============================================================================== +# Application URLs +# ============================================================================== +VITE_DOCS_URL=http://localhost:5173/docs +VITE_GAME_URL=http://localhost:5175 + +# ============================================================================== +# CORS Configuration (for auth service) +# ============================================================================== +# Comma-separated list of allowed origins for CORS +# Example: CORS_ALLOWED_ORIGINS=https://docs.example.com,https://site.example.com +CORS_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:5174,http://localhost:5175 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..7f39382 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,113 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + # TypeScript type checking and build + typescript-check: + name: TypeScript Check + runs-on: ubuntu-latest + strategy: + matrix: + app: [docs, site] + steps: + - uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + cache: "pnpm" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Type check ${{ matrix.app }} + working-directory: apps/${{ matrix.app }} + run: pnpm check + + - name: Build ${{ matrix.app }} + working-directory: apps/${{ matrix.app }} + run: pnpm build + + # Rust tests and formatting check + rust-check: + name: Rust Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt, clippy + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v4 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo build + uses: actions/cache@v4 + with: + path: apps/game/target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Check formatting + working-directory: apps/game + run: cargo fmt -- --check + + - name: Run Clippy + working-directory: apps/game + run: cargo clippy -- -D warnings + + - name: Run tests + working-directory: apps/game + run: cargo test + + # Security audit for dependencies + security-audit: + name: Security Audit + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "22" + cache: "pnpm" + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run npm audit + run: pnpm audit --audit-level moderate + + - name: Check for leaked secrets + uses: trufflesecurity/trufflehog@main + with: + path: ./ + base: ${{ github.event.repository.default_branch }} + head: HEAD diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 0000000..3c093e0 --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,18 @@ +name: Commit Lint + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + commitlint: + name: Lint Commit Messages + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: wagoid/commitlint-github-action@v6 + with: + configFile: .commitlint.config.js diff --git a/.gitignore b/.gitignore index cac5382..38443a1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,13 +8,33 @@ coverage/ .parcel-cache/ .cache/ .DS_Store + +# Environment files (never commit these) .env .env.local .env.*.local + +# SpacetimeDB spacetime.local.json +.spacetime-dev/ + +# TypeScript *.tsbuildinfo vite.config.js vite.config.d.ts + +# Playwright .playwright-mcp/ -.spacetime-dev/ + +# Rust target/ + +# Database files (SQLite, SpacetimeDB, etc.) +*.db +*.db-shm +*.db-wal +*.sqlite +*.sqlite3 + +# CI/CD local testing +.github/workflows/.local* diff --git a/AGENTS.md b/AGENTS.md index e2a4ed8..e0ea3e3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # VOID::NAV — Monorepo Root -Single-player open-world space exploration RPG. Windward Horizon in space with FTL-style combat. +Single-player narrative-driven space exploration saga. Windward meets Stellaris with AI-generated storytelling in the style of The Templin Institute. ## Directory Map @@ -10,29 +10,26 @@ Single-player open-world space exploration RPG. Windward Horizon in space with F | `apps/game` | Playable game client — **Rust + Bevy** (independent of the JS/TS workspace) | | `apps/site` | Public landing page (Vite + React) | | `packages/ui` | Shared UI primitives and design tokens for the TS apps | -| `services/spacetimedb` | SpacetimeDB TypeScript backend module (authoritative game state) | | `scripts/` | Dev tooling (dev.sh startup script) | | `archive/` | Legacy pre-monorepo files kept for reference | ## Key Files -- `package.json` — pnpm workspace scripts (`dev`, `build`, `check`, `generate:bindings`) +- `package.json` — pnpm workspace scripts (`dev`, `build`, `check`) - `pnpm-workspace.yaml` — workspace glob patterns (covers TS apps only) -- `spacetime.json` — SpacetimeDB module path and binding generation config - `tsconfig.base.json` — Shared TypeScript config (ES2020, React JSX) — does not apply to `apps/game` - `apps/game/Cargo.toml` — Rust manifest for the game binary ## Commands -### JS/TS workspace (docs, site, packages/ui, services) +### JS/TS workspace (docs, site, packages/ui) ```bash -pnpm dev # Full stack: SpacetimeDB + docs/site +pnpm dev # Docs + site servers pnpm dev:docs # Docs only (port 5173) pnpm dev:site # Site only (port 5174) pnpm build # Build all TS packages pnpm check # Typecheck all TS packages -pnpm generate:bindings # Regenerate SpacetimeDB TypeScript bindings ``` ### Rust game (`apps/game`) @@ -47,13 +44,11 @@ cargo clippy # Lint ## Architecture Notes -- **Two independent toolchains coexist**: the pnpm/TS workspace (docs, site, UI lib, SpacetimeDB backend) and the Cargo/Rust game client. They share no code. -- **SpacetimeDB** remains the authoritative persistence layer. The game client will connect to it via the SpacetimeDB Rust SDK when wired up (TS bindings generated by `pnpm generate:bindings` are consumed by the docs prototype, not the game). +- **Two independent toolchains coexist**: the pnpm/TS workspace (docs, site, UI lib) and the Cargo/Rust game client. They share no code. +- **V1 is single-player** with local persistence. Future multiplayer servers will be added as an optional enhancement. - **Naming follows RFC 344**: see `apps/game/AGENTS.md` for Rust/Bevy conventions. ## Conventions (TS apps) -- SpacetimeDB is the persistence layer from day 1 — no localStorage for game state in the docs prototype - TS apps use Tailwind CSS v4 with custom design tokens from `packages/ui` - 3D rendering in `apps/docs` uses React Three Fiber + Drei + Three.js -- Module bindings are auto-generated — never edit generated bindings by hand diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..e9fd522 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,146 @@ +# VOID::NAV - AI Agent Guidelines + +## Project Overview + +VOID::NAV is a single-player narrative-driven space exploration game built with: +- **Rust + Bevy 0.16** for the game client (`apps/game/`) +- **TypeScript + React** for docs and site (`apps/docs/`, `apps/site/`) +- **pnpm workspace** monorepo structure + +## Key Technical Patterns + +### Bevy ECS Architecture +- The game uses Bevy's Entity Component System with state-based gameplay +- States: MainMenu, Galaxy, CharacterCreation, StartingBaseSelection, InGame, Options +- Systems use `run_if(in_state(AppState::InGame))` for state-gated execution +- Components are organized by feature module (ai, movement, galaxy, narrative, etc.) + +### Time API (Bevy 0.16) +- Use `time.delta_secs()` NOT `time.delta_seconds()` for delta time +- Time is accessed as `Res