Initial commit
This commit is contained in:
174
js/pages/techstack.js
Normal file
174
js/pages/techstack.js
Normal file
@@ -0,0 +1,174 @@
|
||||
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 (
|
||||
<div className="content-inner">
|
||||
<h1 style={{ marginBottom: '8px' }}>Technical Direction</h1>
|
||||
<p style={{ color: 'var(--fg-dim)', fontSize: '0.95rem', maxWidth: '680px' }}>
|
||||
Each layer is chosen for iteration speed during the prototype phase. Architecture is designed
|
||||
so any layer can be replaced as the game evolves.
|
||||
</p>
|
||||
|
||||
{/* Decision tabs */}
|
||||
<div style={{ display: 'flex', gap: 'var(--sp-2)', marginBottom: 'var(--sp-6)', flexWrap: 'wrap' }}>
|
||||
{tabs.map(t => (
|
||||
<button
|
||||
key={t.id}
|
||||
className={`btn btn-sm${activeTab === t.id ? ' btn-primary' : ''}`}
|
||||
onClick={() => setActiveTab(t.id)}
|
||||
>
|
||||
{t.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Active decision */}
|
||||
<div className="card" style={{ marginBottom: 'var(--sp-6)' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 'var(--sp-3)', marginBottom: 'var(--sp-4)' }}>
|
||||
<span style={{ fontFamily: 'var(--font-mono)', fontSize: '0.7rem', color: 'var(--accent)', textTransform: 'uppercase', letterSpacing: '0.05em' }}>
|
||||
{activeTab}
|
||||
</span>
|
||||
<span style={{ width: '1px', height: '16px', background: 'var(--border)' }} />
|
||||
<span style={{ fontFamily: 'var(--font-display)', fontSize: '1.3rem', fontWeight: 600, color: 'var(--fg-bright)' }}>
|
||||
{d.choice}
|
||||
</span>
|
||||
</div>
|
||||
<p style={{ color: 'var(--fg-dim)', fontSize: '0.9rem', marginBottom: 'var(--sp-4)' }}>
|
||||
<strong style={{ color: 'var(--fg)' }}>Why:</strong> {d.reason}
|
||||
</p>
|
||||
<div style={{ background: 'var(--surface-raised)', borderRadius: 'var(--radius-md)', padding: 'var(--sp-4)', fontSize: '0.85rem', color: 'var(--fg-dim)' }}>
|
||||
<strong style={{ color: 'var(--muted)' }}>Why not the alternatives:</strong> {d.whyNot}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Full decision table */}
|
||||
<div className="section-header">
|
||||
<span className="section-num">TECH-ALL</span>
|
||||
<h2 style={{ margin: 0 }}>Decision Matrix</h2>
|
||||
</div>
|
||||
|
||||
<table className="data-table">
|
||||
<thead>
|
||||
<tr><th>Layer</th><th>Choice</th><th>Reason</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style={{ color: 'var(--cyan)' }}>Frontend</td>
|
||||
<td>Vite + React + TypeScript</td>
|
||||
<td style={{ color: 'var(--fg-dim)' }}>Fast client-side app, no SSR complexity.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{ color: 'var(--purple)' }}>3D Rendering</td>
|
||||
<td>React Three Fiber</td>
|
||||
<td style={{ color: 'var(--fg-dim)' }}>Declarative React renderer for Three.js.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{ color: 'var(--green)' }}>UI State</td>
|
||||
<td>Zustand</td>
|
||||
<td style={{ color: 'var(--fg-dim)' }}>Simple local state for panels and UI.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{ color: 'var(--accent)' }}>Backend</td>
|
||||
<td>SpacetimeDB</td>
|
||||
<td style={{ color: 'var(--fg-dim)' }}>Real-time backend with reducers and subscriptions.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{ color: 'var(--fg-dim)' }}>Styling</td>
|
||||
<td>Tailwind CSS</td>
|
||||
<td style={{ color: 'var(--fg-dim)' }}>Fast iteration for panels, tables, HUDs.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style={{ color: 'var(--muted)' }}>Auth</td>
|
||||
<td>SpacetimeDB identity</td>
|
||||
<td style={{ color: 'var(--fg-dim)' }}>Simple identity first; add auth later.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{/* File structure */}
|
||||
<div className="section-header" style={{ marginTop: 'var(--sp-8)' }}>
|
||||
<span className="section-num">TECH-FS</span>
|
||||
<h2 style={{ margin: 0 }}>Starter File Structure</h2>
|
||||
</div>
|
||||
|
||||
<div className="callout callout-info" style={{ marginBottom: 'var(--sp-5)', fontSize: '0.82rem' }}>
|
||||
<strong>Note:</strong> The file structure below is the <em>production target</em> for a Vite + React + TypeScript project.
|
||||
The current prototype uses a simpler layout: <code>js/pages/</code>, <code>js/components/</code>, <code>js/demos/</code>, <code>js/lib/</code>, and <code>css/</code> —
|
||||
a flat structure loaded via Babel standalone without a build step. The prototype structure will migrate to the layout below when moving to Vite.
|
||||
</div>
|
||||
|
||||
<div className="code-block">
|
||||
<code>
|
||||
<span className="cm">{'//'} Starter project layout</span><br/>
|
||||
<span className="kw">/client/src/app</span> <span className="cm">{' //'} App shell and providers</span><br/>
|
||||
<span className="kw">/client/src/network</span> <span className="cm">{' //'} SpacetimeDB client, subscriptions</span><br/>
|
||||
<span className="kw">/client/src/game</span> <span className="cm">{' //'} Renderer-independent types, view models</span><br/>
|
||||
<span className="kw">/client/src/store</span> <span className="cm">{' //'} Zustand stores</span><br/>
|
||||
<span className="kw">/client/src/renderers/r3f</span> <span className="cm">{'//'} R3F scene, meshes, camera</span><br/>
|
||||
<span className="kw">/client/src/ui</span> <span className="cm">{' //'} HUD, inventory, market, chat</span><br/>
|
||||
<span className="kw">/server-spacetime/src</span> <span className="cm">{' //'} SpacetimeDB module, reducers</span><br/>
|
||||
</code>
|
||||
</div>
|
||||
|
||||
<h3>Packages</h3>
|
||||
<table className="data-table">
|
||||
<thead><tr><th>Package</th><th>Purpose</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td>vite, react, react-dom, typescript</td><td>Core frontend.</td></tr>
|
||||
<tr><td>three, @react-three/fiber, @react-three/drei</td><td>3D scene and helper controls.</td></tr>
|
||||
<tr><td>zustand</td><td>Local UI/game view state.</td></tr>
|
||||
<tr><td>tailwindcss</td><td>Panel and HUD styling.</td></tr>
|
||||
<tr><td>spacetimedb TS client</td><td>Backend connection, reducers, subscriptions.</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
window.GDD.TechStackPage = TechStackPage;
|
||||
Reference in New Issue
Block a user