Restructure into pnpm monorepo with game shell, docs, and SpacetimeDB backend
- Restructure flat static prototype into pnpm workspace monorepo - apps/game: playable shell with R3F 3D scene, HUD, SpacetimeDB connection - apps/docs: design docs and prototypes - apps/site: landing page - packages/ui: shared Button and Panel primitives - services/spacetimedb: backend module (9 tables, 11 reducers) - Archive legacy static files to archive/legacy-static/ - Game loop: connect, undock, target, approach, dock, mine, sell - Add pnpm-workspace.yaml, tsconfig.base.json, spacetime.json
This commit is contained in:
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,5 +1,18 @@
|
||||
node_modules/
|
||||
dist/
|
||||
build/
|
||||
coverage/
|
||||
.turbo/
|
||||
.nx/
|
||||
.vite/
|
||||
.parcel-cache/
|
||||
.cache/
|
||||
.DS_Store
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
spacetime.local.json
|
||||
*.tsbuildinfo
|
||||
vite.config.js
|
||||
vite.config.d.ts
|
||||
.playwright-mcp/
|
||||
|
||||
91
README.md
91
README.md
@@ -1,37 +1,84 @@
|
||||
# VOID::NAV
|
||||
|
||||
Vite + React + TypeScript documentation and prototype hub for the Space-Game project.
|
||||
VOID::NAV is now a pnpm workspace monorepo for the game website, living design docs, browser game shell, and SpacetimeDB backend module.
|
||||
|
||||
## Layout
|
||||
|
||||
```text
|
||||
apps/docs Existing docs, interactive demos, and vertical slice
|
||||
apps/site Public landing page / game website
|
||||
apps/game Playable game shell connected to SpacetimeDB bindings
|
||||
packages/ui Small shared UI primitives and CSS tokens
|
||||
services/spacetimedb TypeScript SpacetimeDB module
|
||||
archive/legacy-static Legacy static prototype files kept for reference
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js 24+
|
||||
- pnpm 9+
|
||||
- SpacetimeDB CLI for backend build, generation, and local DB runs
|
||||
|
||||
The SpacetimeDB CLI is not vendored. Frontend builds use the committed placeholder bindings in `apps/game/src/module_bindings`; run `pnpm generate:bindings` after installing the CLI to replace them with generated bindings.
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm dev
|
||||
pnpm dev:docs
|
||||
pnpm dev:site
|
||||
pnpm dev:game
|
||||
```
|
||||
|
||||
## Build
|
||||
Default ports:
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
- docs: `http://localhost:5173/docs`
|
||||
- site: `http://localhost:5174`
|
||||
- game: `http://localhost:5175`
|
||||
|
||||
## Routes
|
||||
|
||||
- `/` - landing page
|
||||
- `/docs` - documentation overview
|
||||
- `/docs/demos/*` - converted interactive demos
|
||||
- `/docs/prototypes/game-hud` - HUD style reference for future demos
|
||||
- `/app` - future game application shell
|
||||
|
||||
## Browser Routing
|
||||
|
||||
This app uses browser-history routes. The Vite dev server works without extra setup.
|
||||
Static production hosting must rewrite all routes to `index.html`.
|
||||
|
||||
Example Netlify rule:
|
||||
The public site links to docs and game via:
|
||||
|
||||
```text
|
||||
/* /index.html 200
|
||||
VITE_DOCS_URL=http://localhost:5173/docs
|
||||
VITE_GAME_URL=http://localhost:5175
|
||||
```
|
||||
|
||||
For Vercel or another static host, configure the equivalent SPA fallback to `index.html`.
|
||||
The game shell reads:
|
||||
|
||||
```text
|
||||
VITE_SPACETIME_URI=http://localhost:3000
|
||||
VITE_SPACETIME_DATABASE=void-nav-dev
|
||||
```
|
||||
|
||||
## Builds
|
||||
|
||||
```bash
|
||||
pnpm --filter @void-nav/docs build
|
||||
pnpm --filter @void-nav/site build
|
||||
pnpm --filter @void-nav/game build
|
||||
pnpm build
|
||||
pnpm check
|
||||
```
|
||||
|
||||
## SpacetimeDB
|
||||
|
||||
Root `spacetime.json` points at `services/spacetimedb` and generates TypeScript bindings into `apps/game/src/module_bindings`.
|
||||
|
||||
With the CLI installed:
|
||||
|
||||
```bash
|
||||
spacetime build --module-path services/spacetimedb
|
||||
pnpm generate:bindings
|
||||
pnpm dev:db
|
||||
```
|
||||
|
||||
`pnpm dev:db` targets the SpacetimeDB CLI server nickname `local` so development publishes to `http://127.0.0.1:3000` instead of any configured cloud default.
|
||||
|
||||
Initial reducers:
|
||||
|
||||
- `connectPlayer(displayName: string)`
|
||||
- `renamePlayer(displayName: string)`
|
||||
- `seedWorld()`
|
||||
- `ping()`
|
||||
|
||||
The game shell calls `connectPlayer` after connection, subscribes to starter shell rows, and displays connection, player, ship, system, station, and reducer status. When SpacetimeDB is unavailable or bindings are still placeholders, it shows a clear disconnected/error state.
|
||||
|
||||
29
apps/docs/package.json
Normal file
29
apps/docs/package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "@void-nav/docs",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --host 0.0.0.0",
|
||||
"build": "tsc --noEmit && vite build",
|
||||
"check": "tsc --noEmit",
|
||||
"preview": "vite preview --host 0.0.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-three/drei": "^9.122.0",
|
||||
"@react-three/fiber": "^8.17.10",
|
||||
"@tailwindcss/vite": "^4.3.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^6.30.1",
|
||||
"tailwindcss": "^4.3.0",
|
||||
"three": "^0.160.0",
|
||||
"vite": "^7.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.3.23",
|
||||
"@types/react-dom": "^18.3.7",
|
||||
"@types/three": "^0.160.0",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 309 KiB After Width: | Height: | Size: 309 KiB |
|
Before Width: | Height: | Size: 273 KiB After Width: | Height: | Size: 273 KiB |
|
Before Width: | Height: | Size: 246 KiB After Width: | Height: | Size: 246 KiB |
415
apps/docs/public/docs/vertical-slice-evaluation.md
Normal file
415
apps/docs/public/docs/vertical-slice-evaluation.md
Normal file
@@ -0,0 +1,415 @@
|
||||
# Vertical Slice Evaluation
|
||||
|
||||
**Date:** 2026-05-31
|
||||
**Scope:** Compare the current playable game implementation against the MVP Loop Slice demo and the Era 1 roadmap goals.
|
||||
|
||||
---
|
||||
|
||||
## Executive Assessment
|
||||
|
||||
The project has a strong vertical-slice prototype in the docs app, but the standalone game app is still a Phase 0 technical shell. The MVP Loop Slice demonstrates the intended solo loop and connects many previously standalone demos through a shared browser session. The actual game app connects to SpacetimeDB, creates/subscribes to starter rows, and exposes connection/reducer status, but it does not yet implement the playable slice loop.
|
||||
|
||||
In practical terms:
|
||||
|
||||
- **Design/demo confidence is high.** The docs app proves the target loop and system UX at prototype fidelity.
|
||||
- **Runtime implementation readiness is early.** The game app has connection plumbing and starter persistence only.
|
||||
- **The main gap is migration from prototype state to authoritative game state.** The loop exists in localStorage and React state, not in SpacetimeDB tables/reducers.
|
||||
- **Phase 0 is partially complete.** SpacetimeDB connectivity, starter player/ship/system/station rows, and reducer invocation exist. The rendered star system, tick loop, 3D scene, and gameplay commands are not yet present in the game app.
|
||||
|
||||
---
|
||||
|
||||
## Baselines Compared
|
||||
|
||||
### Intended Era 1 Vertical Slice
|
||||
|
||||
The roadmap defines Era 1 as a single-player proof of concept using local SpacetimeDB from day one. The minimum full loop is:
|
||||
|
||||
1. Boot the game and connect to local SpacetimeDB.
|
||||
2. Render a single star system with station and asteroids.
|
||||
3. Undock.
|
||||
4. Navigate to an asteroid belt.
|
||||
5. Mine ore into cargo.
|
||||
6. Return and dock.
|
||||
7. Refine ore.
|
||||
8. Fit or confirm a module.
|
||||
9. Sell goods on a market.
|
||||
10. Optionally run a combat trial.
|
||||
11. Persist state through SpacetimeDB, not localStorage.
|
||||
|
||||
### Docs-App MVP Loop Slice
|
||||
|
||||
The docs app already implements a connected prototype of that loop:
|
||||
|
||||
- Session/objective flow: `apps/docs/src/prototypes/game-slice/sliceObjectives.ts`
|
||||
- Local session state and event reducer: `apps/docs/src/prototypes/game-slice/gameSliceState.ts`
|
||||
- Action gating and contextual commands: `apps/docs/src/prototypes/game-slice/sliceController.ts`
|
||||
- Runtime controller: `apps/docs/src/prototypes/game-slice/useSliceController.ts`
|
||||
- Loop shell/UI composition: `apps/docs/src/prototypes/game-slice/SeamlessGameLoopSlice.tsx`
|
||||
|
||||
It validates the user-facing flow, command availability, objective tracking, event log, cargo, station services, fitting handoff, market selling, XP awards, Zora observation events, and optional combat branch.
|
||||
|
||||
Its explicit limitation is architectural: it uses local browser persistence and fake/deterministic data. It does not validate backend authority, persistence model, multiplayer path, generated bindings, or SpacetimeDB reducer design.
|
||||
|
||||
### Standalone Game App
|
||||
|
||||
The standalone game app currently validates the connection path:
|
||||
|
||||
- SpacetimeDB connection lifecycle: `apps/game/src/spacetime/useSpacetimeConnection.ts`
|
||||
- Subscription/read facade: `apps/game/src/spacetime/usePlayerSession.ts`
|
||||
- Flight console shell: `apps/game/src/GameShell.tsx`
|
||||
- Starter backend module: `services/spacetimedb/src/index.ts`
|
||||
|
||||
The backend currently provides:
|
||||
|
||||
- `player`
|
||||
- `ship`
|
||||
- `system`
|
||||
- `station`
|
||||
- `server_event`
|
||||
- `connectPlayer`
|
||||
- `renamePlayer`
|
||||
- `seedWorld`
|
||||
- `ping`
|
||||
|
||||
This is useful and necessary, but it is not yet the playable vertical slice.
|
||||
|
||||
---
|
||||
|
||||
## Alignment Matrix
|
||||
|
||||
| Slice expectation | Demo status | Game app status | Gap |
|
||||
|---|---:|---:|---|
|
||||
| App boots | Yes | Yes | Mostly aligned. |
|
||||
| Local SpacetimeDB connection | No | Partial | Game connects, but the slice does not use it. |
|
||||
| Starter player identity | No | Yes | Present in game shell only. |
|
||||
| Starter ship row | No | Yes | Present, but no position/mode/cargo/fitting state. |
|
||||
| Single star system | Yes, fake/system data | Partial | Backend has one system and station; no asteroid rows or scene rendering. |
|
||||
| Station and asteroids visible | Yes | No | Game shell displays data cards only. |
|
||||
| 60fps render / 1Hz sim tick | Prototype timers only | No | No authoritative sim tick or render scene in game app. |
|
||||
| Undock/dock | Yes | No | Needs reducers, row state, and UI commands. |
|
||||
| Local movement / approach target | Yes | No | Needs target/position model and movement reducer/tick. |
|
||||
| Warp/travel handoff | Yes in demos | No | Needs backend travel operation model. |
|
||||
| Mining cycle | Yes | No | Needs asteroid/cargo/mining operation tables and reducers. |
|
||||
| Cargo and inventory | Yes | No | Needs authoritative inventory schema. |
|
||||
| Refining | Yes | No | Needs station service reducer and inventory transaction. |
|
||||
| Fitting | Yes | No | Needs module catalog, ship fitting rows, CPU/PG validation. |
|
||||
| Market selling | Yes | No | Needs market/order/transaction state, even if NPC-only first. |
|
||||
| Combat trial | Yes | No | Needs NPC entity/combat reducer loop. |
|
||||
| Objective tracker | Yes | No | Needs game app UI or server-backed tutorial/objective state. |
|
||||
| Event log | Yes | Partial | Game has server events, but not gameplay events. |
|
||||
| Skills/XP | Yes | No | Needs skill rows and XP reducer. |
|
||||
| Zora Tier 0 hooks | Yes | No | Needs backend state and game UI hooks. |
|
||||
| Persistence | localStorage | Partial SpacetimeDB | Game persists starter rows only; slice state still localStorage. |
|
||||
|
||||
---
|
||||
|
||||
## What Lines Up Well
|
||||
|
||||
### 1. The vertical slice is coherent
|
||||
|
||||
The MVP Loop Slice is not just a gallery of isolated screens. It has a real objective chain:
|
||||
|
||||
`undock -> navigate_to_belt -> mine_ore -> dock_at_station -> refine_ore -> fit_module -> sell_goods -> combat_trial`
|
||||
|
||||
That is the correct shape for Gate 4 and gives implementation a clear target.
|
||||
|
||||
### 2. Command gating is already well modeled
|
||||
|
||||
The slice controller has concrete command availability rules: dock only at stations, mine only at belts, services only while docked, market only with sellable cargo, refining only with enough ore, and busy-state blocking while operations run. These are exactly the rules that should become server-side validation in reducers.
|
||||
|
||||
### 3. The game app has the right backend direction
|
||||
|
||||
The game app already uses SpacetimeDB bindings, reducer calls, subscriptions, identity, and server event rows. This lines up with the roadmap decision to avoid localStorage as the final persistence layer.
|
||||
|
||||
### 4. The demo gallery honestly documents limitations
|
||||
|
||||
The docs already distinguish UX validation from production implementation. That makes the remaining work clearer: the problem is not unknown design, it is backend-backed integration.
|
||||
|
||||
---
|
||||
|
||||
## Key Gaps
|
||||
|
||||
### 1. The demo and the game app use different state models
|
||||
|
||||
The MVP Loop Slice stores a rich `GameSliceSession` in localStorage. The game app stores only starter identity, ship, system, station, and event rows in SpacetimeDB.
|
||||
|
||||
This creates the largest implementation gap. Nearly every field in the slice session needs either a backend table, a derived client view, or an explicit decision that it remains client-only.
|
||||
|
||||
Important missing authoritative state includes:
|
||||
|
||||
- current ship mode: station, flight, travel, mining, docking, combat
|
||||
- ship position and current point of interest
|
||||
- docked station state
|
||||
- active operation with start time and duration
|
||||
- selected target
|
||||
- cargo and cargo capacity
|
||||
- fitted modules
|
||||
- wallet
|
||||
- skills and XP
|
||||
- objectives/tutorial progress
|
||||
- Zora module/state hooks
|
||||
|
||||
### 2. Phase 0 rendering is not implemented in the game app
|
||||
|
||||
The roadmap says Phase 0 is done when the app shows a star system with a station and three asteroids, updates local state on a tick, and persists through SpacetimeDB. The current game app is a useful diagnostic console, but it does not render the playable space scene or asteroid targets.
|
||||
|
||||
### 3. Backend schema is intentionally minimal
|
||||
|
||||
The backend module currently supports connection and starter world creation. It does not yet contain the tables required for the slice loop:
|
||||
|
||||
- points of interest or asteroid belts
|
||||
- inventory/cargo
|
||||
- wallet transactions
|
||||
- mining operations
|
||||
- refining jobs
|
||||
- module catalog
|
||||
- ship fittings
|
||||
- market orders or NPC buy prices
|
||||
- skills
|
||||
- objectives/tutorial state
|
||||
- NPCs/combat state
|
||||
|
||||
### 4. Reducers do not yet represent gameplay commands
|
||||
|
||||
The current reducers are connection/admin-level:
|
||||
|
||||
- `connectPlayer`
|
||||
- `renamePlayer`
|
||||
- `seedWorld`
|
||||
- `ping`
|
||||
|
||||
The slice needs command reducers such as:
|
||||
|
||||
- `undock`
|
||||
- `dock`
|
||||
- `selectTarget`
|
||||
- `startApproach`
|
||||
- `completeMovement` or server tick movement resolution
|
||||
- `startMining`
|
||||
- `stopMining`
|
||||
- `completeMiningCycle`
|
||||
- `refineOre`
|
||||
- `fitModule`
|
||||
- `unfitModule`
|
||||
- `sellItemToNpcMarket`
|
||||
- `startCombatTrial`
|
||||
- `resolveCombatTick`
|
||||
|
||||
### 5. The demo validates flow, not balance or backend correctness
|
||||
|
||||
The slice has deterministic prices, deterministic refining, simplified XP, and simplified combat. It proves the player journey, but not the production economy, exploit resistance, transaction safety, concurrent updates, or server authority.
|
||||
|
||||
### 6. Naming and world setup are not fully unified
|
||||
|
||||
The game shell seeds `solace` / `solace-prime` / "Solace Prime Orbital". The slice defaults to `sol` / `sol-station-0` / "Jita IV - Moon 4". This is acceptable for prototypes, but it will create migration friction if not unified before gameplay reducers are added.
|
||||
|
||||
### 7. Existing standalone demos are only partially integrated
|
||||
|
||||
The docs note that several demos can consume the slice session, but core effects still remain demo-local. For example, fitting can update slice modules and combat can emit victory, but the final game still needs one authoritative source of truth where fitting affects mining/combat stats and combat affects wallet/cargo/ship state.
|
||||
|
||||
---
|
||||
|
||||
## Phase Readiness
|
||||
|
||||
### Phase 0 - Local Skeleton
|
||||
|
||||
**Status:** Partially implemented.
|
||||
|
||||
Done:
|
||||
|
||||
- pnpm workspace exists.
|
||||
- standalone game app exists.
|
||||
- SpacetimeDB module exists.
|
||||
- generated/placeholder bindings are committed.
|
||||
- client attempts connection and handles unavailable backend clearly.
|
||||
- starter player, ship, system, station, and events exist.
|
||||
|
||||
Remaining:
|
||||
|
||||
- render a star system in the game app.
|
||||
- add station plus three asteroid targets to backend state.
|
||||
- add local simulation tick concept.
|
||||
- persist position/mode/state through SpacetimeDB.
|
||||
- replace diagnostic-only console with first playable flight shell.
|
||||
|
||||
### Phase 1 - Movement & Commands
|
||||
|
||||
**Status:** Prototyped, not implemented in game app.
|
||||
|
||||
The movement demo and slice validate UX, target selection, approach, ETA/progress, and arrival. The game app needs backend-backed target state, command reducers, and client interpolation.
|
||||
|
||||
### Phase 2 - Mining & Inventory
|
||||
|
||||
**Status:** Prototyped, not implemented in game app.
|
||||
|
||||
The slice validates mining cycles and cargo filling. The game app needs inventory rows, asteroid/belt rows, mining operation state, cargo capacity, and transaction-safe ore insertion.
|
||||
|
||||
### Phase 3 - Combat
|
||||
|
||||
**Status:** Prototyped, not implemented in game app.
|
||||
|
||||
The demo validates power allocation and combat feel. The game app needs NPC entities, combat session state, damage resolution, ship health, loot, bounty payout, and failure/death handling.
|
||||
|
||||
### Phase 4 - Fitting
|
||||
|
||||
**Status:** Prototyped, not implemented in game app.
|
||||
|
||||
The fitting demo validates module constraints and UI feel. The game app needs module catalog rows, fitted module rows, CPU/PG validation in reducers, and stat derivation that affects mining/combat.
|
||||
|
||||
### Phase 5 - Refining & Manufacturing
|
||||
|
||||
**Status:** Refining prototyped; manufacturing not in slice runtime.
|
||||
|
||||
The slice supports ore-to-mineral refining. Manufacturing remains a later implementation gap for the full Era 1 economy loop.
|
||||
|
||||
### Phase 6 - NPC Economy Sim
|
||||
|
||||
**Status:** Market surface prototyped; backend economy not implemented.
|
||||
|
||||
The market demo validates presentation and selling flow. The game app needs NPC price state, transaction reducers, market history, and later regional differences/diffusion.
|
||||
|
||||
### Phase 7 - Single-Player Polish
|
||||
|
||||
**Status:** Design-ready, implementation not started in game app.
|
||||
|
||||
Tutorial/objectives, events, Zora Tier 0, accessibility, persistence, and polish are documented/prototyped in parts, but not integrated into the standalone game.
|
||||
|
||||
---
|
||||
|
||||
## Recommended Implementation Path
|
||||
|
||||
### Step 1 - Promote the slice state into a backend contract
|
||||
|
||||
Create a mapping document or code comments that classify each `GameSliceSession` field as:
|
||||
|
||||
- persisted backend state
|
||||
- derived client state
|
||||
- temporary UI state
|
||||
- prototype-only state to delete
|
||||
|
||||
This prevents blindly copying localStorage structure into SpacetimeDB while still preserving the proven flow.
|
||||
|
||||
### Step 2 - Finish Phase 0 in the game app
|
||||
|
||||
Add the smallest playable world:
|
||||
|
||||
- one system
|
||||
- one station
|
||||
- three asteroid/belt POIs
|
||||
- one starter ship with position, mode, and docked state
|
||||
- a 3D or 2.5D in-space view
|
||||
- a simple read-only HUD showing authoritative rows
|
||||
- a 1Hz server/sim update path or explicit reducer-driven operation completion
|
||||
|
||||
Acceptance check: open the game app, connect to local SpacetimeDB, and see the starter system represented visually rather than only as data cards.
|
||||
|
||||
### Step 3 - Port the command rail one command at a time
|
||||
|
||||
Use the slice action gating as the implementation source for server validation. Add reducers in this order:
|
||||
|
||||
1. `undock`
|
||||
2. `selectTarget`
|
||||
3. `startApproach`
|
||||
4. `dock`
|
||||
5. `startMining`
|
||||
6. `stopMining`
|
||||
7. `refineOre`
|
||||
8. `fitModule`
|
||||
9. `sellItemToNpcMarket`
|
||||
10. `startCombatTrial`
|
||||
|
||||
Each reducer should produce a `server_event` row so the current game shell remains useful while the UI evolves.
|
||||
|
||||
### Step 4 - Add the minimum schema for Gate 1
|
||||
|
||||
For the first integrated gate, implement only what is needed for:
|
||||
|
||||
`navigate to asteroid -> mine -> fill cargo -> dock -> sell ore`
|
||||
|
||||
Minimum tables/fields:
|
||||
|
||||
- ship location/mode/position/docked state
|
||||
- points of interest
|
||||
- cargo/inventory
|
||||
- wallet
|
||||
- active operation
|
||||
- market NPC buy price or station commodity price
|
||||
- event log
|
||||
|
||||
Avoid implementing manufacturing, full market depth, skills, Zora, or combat until Gate 1 works end to end.
|
||||
|
||||
### Step 5 - Replace localStorage handoff with SpacetimeDB-backed session state
|
||||
|
||||
The docs slice can continue to exist as a UX reference, but the standalone game should become the source of truth for vertical-slice progress. Once equivalent reducers exist, either:
|
||||
|
||||
- point the docs slice at the same backend for live validation, or
|
||||
- freeze it as an archived prototype and move active work into `apps/game`.
|
||||
|
||||
### Step 6 - Add focused verification
|
||||
|
||||
Add tests at the reducer/logic level before broad UI tests:
|
||||
|
||||
- connecting creates one player and one starter ship
|
||||
- repeated connect is idempotent
|
||||
- undock changes docked state and mode
|
||||
- movement cannot start while docked
|
||||
- docking only works at a station POI
|
||||
- mining only works at a belt and respects cargo capacity
|
||||
- refining consumes ore and creates minerals
|
||||
- selling removes inventory and increases wallet
|
||||
- invalid fitting is rejected
|
||||
|
||||
---
|
||||
|
||||
## Open Decisions
|
||||
|
||||
1. **Which app is the product surface?**
|
||||
Recommendation: `apps/game` should become the product surface; `apps/docs` remains design/prototype reference.
|
||||
|
||||
2. **How much of the slice UI should be ported?**
|
||||
Recommendation: port the interaction model and command gating, not the localStorage architecture.
|
||||
|
||||
3. **Should Phase 0 include Three.js immediately?**
|
||||
Recommendation: yes, if the target is a space game with Flight Mode as a first-class surface. The docs already have reusable R3F scene pieces that can guide the implementation.
|
||||
|
||||
4. **What is the canonical starter world?**
|
||||
Recommendation: choose one naming/id set before adding gameplay reducers. Prefer production-neutral IDs over inherited EVE names.
|
||||
|
||||
5. **Server tick vs. reducer-scheduled completion?**
|
||||
Recommendation: for early phases, reducer-driven operations with authoritative timestamps are enough. Add a scheduler/tick once NPCs, economy, and combat need autonomous progression.
|
||||
|
||||
---
|
||||
|
||||
## Priority Work List
|
||||
|
||||
### Immediate
|
||||
|
||||
1. Decide canonical starter system/station/POI IDs.
|
||||
2. Add backend POI/asteroid state.
|
||||
3. Add ship mode, position, docked state, wallet, and cargo state.
|
||||
4. Build the game app's first visual system scene.
|
||||
5. Add `undock`, `dock`, and `startApproach` reducers.
|
||||
|
||||
### Next
|
||||
|
||||
1. Add mining operation and cargo reducers.
|
||||
2. Add station sell/refine reducers.
|
||||
3. Port the command rail/objective tracker into `apps/game`.
|
||||
4. Add reducer tests for Gate 1.
|
||||
5. Run a manual Gate 1 playtest.
|
||||
|
||||
### Later
|
||||
|
||||
1. Fitting with CPU/PG validation.
|
||||
2. Combat trial with NPC state and loot.
|
||||
3. Skills/XP progression.
|
||||
4. Zora Tier 0 backend state.
|
||||
5. Manufacturing and deeper NPC economy.
|
||||
|
||||
---
|
||||
|
||||
## Bottom Line
|
||||
|
||||
The game lines up well with the vertical slice at the design and prototype level, but not yet at the playable implementation level. The docs app has already answered "what should the first loop feel like?" The standalone game app is now ready to answer "can that loop run against authoritative SpacetimeDB state?"
|
||||
|
||||
The next milestone should be a narrow Gate 1 implementation in `apps/game`: connect, undock, approach asteroid, mine ore, dock, and sell. That is the shortest path from demo confidence to a real playable vertical slice.
|
||||
@@ -1,9 +1,6 @@
|
||||
import { Navigate, Route, Routes } from "react-router-dom";
|
||||
import { DocsLayout } from "./layouts/DocsLayout";
|
||||
import { SiteLayout } from "./layouts/SiteLayout";
|
||||
import { NotFound } from "./components/NotFound";
|
||||
import { LandingPage } from "./pages/LandingPage";
|
||||
import { ApplicationPage } from "./pages/ApplicationPage";
|
||||
import { OverviewPage } from "./pages/docs/OverviewPage";
|
||||
import { ArchitecturePage } from "./pages/docs/ArchitecturePage";
|
||||
import { TechStackPage } from "./pages/docs/TechStackPage";
|
||||
@@ -18,6 +15,7 @@ import { RoadmapPage } from "./pages/docs/RoadmapPage";
|
||||
import { RisksPage } from "./pages/docs/RisksPage";
|
||||
import { DemoGalleryPage } from "./pages/docs/DemoGalleryPage";
|
||||
import { GapAnalysisPage } from "./pages/docs/GapAnalysisPage";
|
||||
import { VerticalSliceEvaluationPage } from "./pages/docs/VerticalSliceEvaluationPage";
|
||||
import { DesignDocPage } from "./pages/docs/DesignDocPage";
|
||||
import { StarMapDemo } from "./prototypes/existing-demos/StarMapDemo";
|
||||
import { ShipMovementDemo } from "./prototypes/existing-demos/ShipMovementDemo";
|
||||
@@ -38,10 +36,7 @@ import { GameHudPrototype } from "./prototypes/standalone-huds/GameHudPrototype"
|
||||
export function App() {
|
||||
return (
|
||||
<Routes>
|
||||
<Route element={<SiteLayout />}>
|
||||
<Route path="/" element={<LandingPage />} />
|
||||
<Route path="/app" element={<ApplicationPage />} />
|
||||
</Route>
|
||||
<Route path="/" element={<Navigate to="/docs" replace />} />
|
||||
|
||||
<Route path="/docs" element={<DocsLayout />}>
|
||||
<Route index element={<Navigate to="/docs/overview" replace />} />
|
||||
@@ -59,6 +54,7 @@ export function App() {
|
||||
<Route path="risks" element={<RisksPage />} />
|
||||
<Route path="demo-gallery" element={<DemoGalleryPage />} />
|
||||
<Route path="gap-analysis" element={<GapAnalysisPage />} />
|
||||
<Route path="vertical-slice-evaluation" element={<VerticalSliceEvaluationPage />} />
|
||||
<Route path="design-doc" element={<DesignDocPage />} />
|
||||
|
||||
<Route path="demos/starmap" element={<StarMapDemo />} />
|
||||
@@ -26,6 +26,7 @@ export const navSections: NavSection[] = [
|
||||
{ path: "/docs/roadmap", icon: "⊞", label: "Roadmap" },
|
||||
{ path: "/docs/risks", icon: "◬", label: "Risks & Questions" },
|
||||
{ path: "/docs/gap-analysis", icon: "□", label: "Gap Analysis" },
|
||||
{ path: "/docs/vertical-slice-evaluation", icon: "▤", label: "Slice Evaluation" },
|
||||
{ path: "/docs/design-doc", icon: "▣", label: "Design Doc" },
|
||||
],
|
||||
},
|
||||
23
apps/docs/src/pages/docs/VerticalSliceEvaluationPage.tsx
Normal file
23
apps/docs/src/pages/docs/VerticalSliceEvaluationPage.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
// @ts-nocheck
|
||||
export function VerticalSliceEvaluationPage() {
|
||||
return (
|
||||
<div className="mx-auto max-w-content">
|
||||
<h1>Vertical Slice Evaluation</h1>
|
||||
<p style={{ color: "var(--fg-dim)", maxWidth: 720 }}>
|
||||
Current assessment of how the standalone game app lines up against the
|
||||
MVP Loop Slice demo and Era 1 roadmap, including implementation gaps
|
||||
and the recommended next work.
|
||||
</p>
|
||||
<div className="mb-6 rounded-xl border border-border bg-surface p-6 max-md:rounded-lg max-md:p-4 border-l-[3px] border-l-accent" style={{ marginTop: "var(--sp-5)" }}>
|
||||
<h3>Source Document</h3>
|
||||
<p style={{ color: "var(--fg-dim)" }}>
|
||||
Open the markdown evaluation for the full matrix, gap breakdown,
|
||||
phase readiness notes, and priority work list.
|
||||
</p>
|
||||
<a className="inline-flex cursor-pointer items-center gap-2 rounded-lg border border-border bg-surface-raised px-4 py-2 font-body text-[0.8rem] font-medium text-fg transition-all duration-150 hover:border-border-light hover:bg-surface-hover disabled:cursor-not-allowed disabled:opacity-55 border-accent bg-accent font-semibold text-bg hover:bg-accent-hover" href="/docs/vertical-slice-evaluation.md" target="_blank" rel="noreferrer">
|
||||
Open vertical-slice-evaluation.md
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user