window.GDD = window.GDD || {}; function TechStackPage() { const [activeTab, setActiveTab] = React.useState('frontend'); const tabs = [ { id: 'frontend', label: 'Frontend' }, { id: 'rendering', label: '3D Rendering' }, { id: 'state', label: 'State' }, { id: 'backend', label: 'Backend' }, { id: 'styling', label: 'Styling' }, { id: 'auth', label: 'Auth' }, ]; const decisions = { frontend: { choice: 'Vite + React + TypeScript', reason: 'Fast client-side app setup, no server-rendering complexity, good for a real-time game UI.', whyNot: "Next.js is not necessary for the MVP. The prototype is a client-side real-time game, not a content site. Next.js can be introduced later for marketing pages, account pages, SSR, or API routes outside SpacetimeDB.", }, rendering: { choice: 'React Three Fiber', reason: 'Declarative React renderer for Three.js; good for a browser prototype and React integration.', whyNot: "A full engine like Unity or Bevy would slow iteration on panels, tables, forms, chat, and market UX. The gameplay is UI-heavy and economy/social-system-heavy.", }, state: { choice: 'Zustand', reason: 'Simple local state for panels, selection, active tabs, camera preferences, and modal state.', whyNot: "Redux would add ceremony without benefit at prototype scale. Context API re-renders would hurt performance with frequent state updates.", }, backend: { choice: 'SpacetimeDB', reason: 'Real-time backend/database with server-side reducers and live client subscriptions. Authoritative state, persistence, multiplayer all in one.', whyNot: "A custom Node.js + PostgreSQL backend would require building real-time sync, subscriptions, and authoritative game logic from scratch.", }, styling: { choice: 'Tailwind CSS', reason: 'Fast UI iteration for panels, tables, HUDs, and dense game interfaces.', whyNot: "CSS-in-JS adds runtime overhead. Vanilla CSS at this scale would slow panel iteration.", }, auth: { choice: 'SpacetimeDB Identity (MVP)', reason: 'Keep early identity/session handling simple. Add external auth only after core loop works.', whyNot: "Full OAuth/JWT would add complexity before we know the right identity model for the game.", }, }; const d = decisions[activeTab]; return (

Technical Direction

Each layer is chosen for iteration speed during the prototype phase. Architecture is designed so any layer can be replaced as the game evolves.

{/* Decision tabs */}
{tabs.map(t => ( ))}
{/* Active decision */}
{activeTab} {d.choice}

Why: {d.reason}

Why not the alternatives: {d.whyNot}
{/* Full decision table */}
TECH-ALL

Decision Matrix

LayerChoiceReason
Frontend Vite + React + TypeScript Fast client-side app, no SSR complexity.
3D Rendering React Three Fiber Declarative React renderer for Three.js.
UI State Zustand Simple local state for panels and UI.
Backend SpacetimeDB Real-time backend with reducers and subscriptions.
Styling Tailwind CSS Fast iteration for panels, tables, HUDs.
Auth SpacetimeDB identity Simple identity first; add auth later.
{/* File structure */}
TECH-FS

Starter File Structure

Note: The file structure below is the production target for a Vite + React + TypeScript project. The current prototype uses a simpler layout: js/pages/, js/components/, js/demos/, js/lib/, and css/ — a flat structure loaded via Babel standalone without a build step. The prototype structure will migrate to the layout below when moving to Vite.
{'//'} Starter project layout
/client/src/app {' //'} App shell and providers
/client/src/network {' //'} SpacetimeDB client, subscriptions
/client/src/game {' //'} Renderer-independent types, view models
/client/src/store {' //'} Zustand stores
/client/src/renderers/r3f {'//'} R3F scene, meshes, camera
/client/src/ui {' //'} HUD, inventory, market, chat
/server-spacetime/src {' //'} SpacetimeDB module, reducers

Packages

PackagePurpose
vite, react, react-dom, typescriptCore frontend.
three, @react-three/fiber, @react-three/drei3D scene and helper controls.
zustandLocal UI/game view state.
tailwindcssPanel and HUD styling.
spacetimedb TS clientBackend connection, reducers, subscriptions.
); } window.GDD.TechStackPage = TechStackPage;