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 (
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 */}Why: {d.reason}
| Layer | Choice | Reason |
|---|---|---|
| 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. |
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
| Package | Purpose |
|---|---|
| vite, react, react-dom, typescript | Core frontend. |
| three, @react-three/fiber, @react-three/drei | 3D scene and helper controls. |
| zustand | Local UI/game view state. |
| tailwindcss | Panel and HUD styling. |
| spacetimedb TS client | Backend connection, reducers, subscriptions. |