Adopt design comps: dark system, new landing/auth, dashboard shell + canvas
Re-skins the whole app to the dark design comps and wires the new surfaces to
the backend (the /api proxy + auth + schemas are unchanged).
Design system:
- globals.css: remapped @theme tokens to the comp palette (#08080a base, coral
#ff6f61, status cyan/green/amber/purple/teal); token names preserved
- MeshMark: triangle + 3-node brand glyph; cm-flow/cm-blink/cm-halo keyframes
- marketing flipped light → dark
Backend (migration 0012):
- agents.model_binding (persisted on team deploy) + GET /api/claws/{id}/runtime-config
- routine_runs table + scheduler journaling + GET /api/routines/runs
- GET /api/claws/{id}/compartments (anatomy aggregate)
- GET /api/structure/stats (workspace counts)
Frontend:
- Landing: full dark marketing page (hero constellation, deploy ladder,
12-topology taxonomy, recursive execution, compare/Pareto, safety, self-host)
- Auth: dark split-panel AuthShell + comp LoginForm + Clerk SignIn themed dark
- Dashboard shell: TopBar (breadcrumb + live stats + deploy + user) + StatusBar
(runner/sandbox/doors); rail slimmed to 60px + 252px context column
- ConstellationCanvas (radial recursive) replaces the graph view in StructureCanvas;
selecting a claw opens ComputerPanel (apps/now-running/dock); RoutinesPanel
- Claw anatomy view (/claws/[id]/anatomy) from compartments + runtime-config
Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
3eca4ed70c
commit
540c74f42e
@@ -1,13 +1,23 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { z } from "zod";
|
||||
|
||||
import { LeftRail } from "@/components/shell/LeftRail";
|
||||
import { ApiAuthError } from "@/lib/api/http";
|
||||
import { StatusBar } from "@/components/shell/StatusBar";
|
||||
import { TopBar } from "@/components/shell/TopBar";
|
||||
import { ApiAuthError, apiFetch } from "@/lib/api/http";
|
||||
import { fetchClaws, fetchCredits, fetchMe } from "@/lib/api/team";
|
||||
import { fetchCompanies, fetchOrgs, fetchTeams, type GroupSummary } from "@/lib/api/structure";
|
||||
import {
|
||||
fetchCompanies,
|
||||
fetchOrgs,
|
||||
fetchStats,
|
||||
fetchTeams,
|
||||
type GroupSummary,
|
||||
type StructureStats,
|
||||
} from "@/lib/api/structure";
|
||||
import type { Agent, Credits, User } from "@/lib/api/schemas";
|
||||
|
||||
// Every workspace page shares the persistent rail (§4). This layout reads
|
||||
// only path-level data — search params stay client-side (see panel-params).
|
||||
// Every workspace page shares the persistent shell (top bar + structure rail +
|
||||
// context column + status bar). The layout server-fetches the chrome data once.
|
||||
export default async function WorkspaceLayout({
|
||||
children,
|
||||
}: Readonly<{ children: React.ReactNode }>) {
|
||||
@@ -17,16 +27,24 @@ export default async function WorkspaceLayout({
|
||||
let orgs: GroupSummary[];
|
||||
let companies: GroupSummary[];
|
||||
let teams: GroupSummary[];
|
||||
let stats: StructureStats | null;
|
||||
let doors: number;
|
||||
try {
|
||||
// Structure lists are non-critical chrome — never let one fail the shell.
|
||||
// Non-critical chrome — never let one failed fetch break the shell.
|
||||
const opt = <T,>(p: Promise<T>, fallback: T) => p.catch(() => fallback);
|
||||
const groups = <T,>(p: Promise<T[]>) => p.catch(() => [] as T[]);
|
||||
[user, roster, credits, orgs, companies, teams] = await Promise.all([
|
||||
[user, roster, credits, orgs, companies, teams, stats, doors] = await Promise.all([
|
||||
fetchMe(),
|
||||
fetchClaws(),
|
||||
fetchCredits(),
|
||||
groups(fetchOrgs()),
|
||||
groups(fetchCompanies()),
|
||||
groups(fetchTeams()),
|
||||
opt(fetchStats(), null),
|
||||
opt(
|
||||
apiFetch(z.array(z.unknown()), "/api/approvals").then((a) => a.length),
|
||||
0,
|
||||
),
|
||||
]);
|
||||
} catch (error) {
|
||||
if (error instanceof ApiAuthError) {
|
||||
@@ -35,16 +53,19 @@ export default async function WorkspaceLayout({
|
||||
throw error;
|
||||
}
|
||||
return (
|
||||
<div className="flex min-h-dvh">
|
||||
<LeftRail
|
||||
user={user}
|
||||
roster={roster}
|
||||
orgs={orgs}
|
||||
companies={companies}
|
||||
teams={teams}
|
||||
creditsBalance={credits.available}
|
||||
/>
|
||||
<main className="min-w-0 flex-1">{children}</main>
|
||||
<div className="flex h-dvh flex-col">
|
||||
<TopBar user={user} stats={stats} />
|
||||
<div className="flex min-h-0 flex-1">
|
||||
<LeftRail
|
||||
roster={roster}
|
||||
orgs={orgs}
|
||||
companies={companies}
|
||||
teams={teams}
|
||||
creditsBalance={credits.available}
|
||||
/>
|
||||
<main className="min-w-0 flex-1 overflow-y-auto">{children}</main>
|
||||
</div>
|
||||
<StatusBar stats={stats} doors={doors} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user