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:
2026-05-31 17:56:56 -04:00
parent 436f282fa8
commit 316a44661b
234 changed files with 3717 additions and 101 deletions

View File

@@ -0,0 +1,11 @@
import { Link } from "react-router-dom";
export function NotFound() {
return (
<div className="mx-auto max-w-content">
<h1>Page Not Found</h1>
<p className="text-fg-dim">The requested route does not exist.</p>
<Link className="inline-flex items-center gap-2 rounded-lg border border-accent bg-accent px-4 py-2 text-[0.8rem] font-semibold text-bg transition-all duration-150 hover:bg-accent-hover" to="/docs">Back to documentation</Link>
</div>
);
}

View File

@@ -0,0 +1,68 @@
import { NavLink } from "react-router-dom";
import { navSections } from "../data/nav";
type SidebarProps = {
collapsed: boolean;
};
export function Sidebar({ collapsed }: SidebarProps) {
return (
<aside
className={[
"z-10 flex h-screen flex-col overflow-hidden border-r border-border bg-surface transition-[width,min-width] duration-[250ms] max-md:h-auto max-md:max-h-[142px] max-md:w-full max-md:min-w-0 max-md:flex-shrink-0 max-md:border-r-0 max-md:border-b",
collapsed ? "w-sidebar-collapsed min-w-sidebar-collapsed max-md:w-full" : "w-sidebar min-w-sidebar",
].join(" ")}
>
<div
className={[
"flex min-h-topbar items-center gap-3 border-b border-border px-5 py-4 max-md:min-h-[38px] max-md:justify-start max-md:px-4 max-md:py-2",
collapsed ? "justify-center px-4" : "",
].join(" ")}
>
<div
className={[
"overflow-hidden whitespace-nowrap font-mono text-[0.8rem] font-bold uppercase tracking-[0.05em] text-accent max-md:text-[0.72rem]",
collapsed ? "text-0 max-md:text-[0.72rem]" : "",
].join(" ")}
>
GDD<span className="text-cyan">::</span>DOCS
</div>
</div>
<nav
className={[
"flex-1 overflow-y-auto px-3 py-3 max-md:flex max-md:gap-2 max-md:overflow-x-auto max-md:overflow-y-hidden max-md:px-3 max-md:pb-3 max-md:pt-2",
collapsed ? "px-2 py-2" : "",
].join(" ")}
>
{navSections.map((section) => (
<div key={section.title} className="max-md:flex max-md:flex-none max-md:gap-2">
<div
className={[
"overflow-hidden whitespace-nowrap px-3 pb-2 pt-4 font-mono text-[0.65rem] uppercase tracking-[0.1em] text-muted max-md:hidden",
collapsed ? "h-2 p-2 text-0" : "",
].join(" ")}
>
{section.title}
</div>
{section.items.map((item) => (
<NavLink
key={item.path}
className={({ isActive }) =>
[
"mb-0.5 flex select-none items-center gap-3 overflow-hidden whitespace-nowrap rounded-lg px-3 py-2 text-[0.85rem] text-fg-dim no-underline transition-all duration-150 hover:bg-surface-raised hover:text-fg-bright max-md:mb-0 max-md:justify-start",
collapsed ? "justify-center p-3 max-md:px-3 max-md:py-2" : "",
isActive ? "border border-accent/25 bg-accent/8 text-accent" : "",
].join(" ")
}
to={item.path}
>
<span className="min-w-5 text-center text-base">{item.icon}</span>
<span className={collapsed ? "hidden max-md:inline" : ""}>{item.label}</span>
</NavLink>
))}
</div>
))}
</nav>
</aside>
);
}

View File

@@ -0,0 +1,37 @@
import { Link, useLocation } from "react-router-dom";
import { pageTitles } from "../data/nav";
type TopBarProps = {
collapsed: boolean;
onToggle: () => void;
};
export function TopBar({ collapsed, onToggle }: TopBarProps) {
const location = useLocation();
const meta = pageTitles.get(location.pathname);
const section = meta?.section?.includes("Demo") || meta?.section?.includes("Prototype") ? "Demos" : "Docs";
const title = meta?.title ?? "Overview";
return (
<div className="flex h-topbar min-h-topbar min-w-0 items-center gap-4 border-b border-border bg-surface px-5 text-[0.8rem] max-md:gap-2 max-md:px-3">
<button
className="flex cursor-pointer items-center rounded border border-border bg-transparent px-2 py-1 text-base text-muted transition-all duration-150 hover:border-border-light hover:text-fg"
onClick={onToggle}
>
{collapsed ? "→" : "←"}
</button>
<div className="flex min-w-0 items-center gap-2 overflow-hidden whitespace-nowrap font-mono text-[0.75rem] text-muted max-md:flex-1">
<Link className="text-inherit no-underline" to="/">VOID::NAV</Link>
<span className="text-border-light">/</span>
<span>{section}</span>
<span className="text-border-light">/</span>
<span className="overflow-hidden text-ellipsis text-fg-bright">{title}</span>
</div>
<div className="ml-auto flex items-center gap-4 whitespace-nowrap font-mono text-[0.7rem] text-muted max-md:hidden">
<span><span className="mr-1 inline-block size-1.5 rounded-full bg-green shadow-[0_0_6px_var(--color-green)]" /> Connected</span>
<span className="text-accent"></span>
<span>Prototype v0.1.0</span>
</div>
</div>
);
}