diff --git a/docs/superpowers/plans/2026-04-22-sanctum-web-layout-redesign.md b/docs/superpowers/plans/2026-04-22-sanctum-web-layout-redesign.md new file mode 100644 index 0000000..3445552 --- /dev/null +++ b/docs/superpowers/plans/2026-04-22-sanctum-web-layout-redesign.md @@ -0,0 +1,386 @@ +# sanctum-web Layout Redesign Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Fork stoatchat/for-web into sanctum-web, fix the root layout so the message area fills the screen properly, and deploy it to mithraic.space/app via Forgejo CI. + +**Architecture:** The root layout lives in two files — `Interface.tsx` (the grid shell) and `Sidebar.tsx` (server list + channel list). Both use Panda CSS (`styled-system/jsx`). We replace the loose flex layout with an explicit CSS Grid, add `min-width: 0` guards on grid children, and wire up a Forgejo Actions pipeline that builds and rsyncs to the VPS on every push to main. + +**Tech Stack:** Solid.js, Vite, TypeScript, Panda CSS (`styled-system/jsx`), pnpm monorepo, Forgejo Actions, rsync + +--- + +## File Map + +| Action | Path | Purpose | +|---|---|---| +| Clone | `git.mithraic.cloud/ad3laid3/sanctum-web` | The fork (already created) | +| Modify | `packages/client/src/Interface.tsx` | Root grid shell — Layout + Content styled components | +| Modify | `packages/client/src/interface/Sidebar.tsx` | Server list + channel list sizing | +| Create | `.forgejo/workflows/deploy.yml` | CI: build + rsync to VPS on push to main | +| Create | `packages/client/.env` | API URLs pointing at mithraic.space services | + +--- + +## Task 1: Clone the fork and add upstream remote + +**Files:** +- Working directory: wherever you keep projects locally + +- [ ] **Step 1: Clone the fork** + +```bash +git clone https://git.mithraic.cloud/ad3laid3/sanctum-web +cd sanctum-web +``` + +- [ ] **Step 2: Add the upstream so you can pull fixes from stoatchat later** + +```bash +git remote add upstream https://github.com/stoatchat/for-web +git fetch upstream +``` + +- [ ] **Step 3: Install dependencies** + +```bash +pnpm install +``` + +- [ ] **Step 4: Confirm dev server starts** + +```bash +cd packages/client +pnpm dev +``` + +Expected: Vite dev server starts, browser opens the app (will show login screen since no backend is configured yet — that's fine). + +- [ ] **Step 5: Commit the baseline (upstream content as-is)** + +```bash +cd ../.. +git add . +git commit -m "chore: initial fork from stoatchat/for-web" +git push origin main +``` + +--- + +## Task 2: Configure environment for mithraic.space + +**Files:** +- Create: `packages/client/.env` + +- [ ] **Step 1: Create the env file** + +```bash +cat > packages/client/.env << 'EOF' +VITE_API_URL=https://mithraic.space/api +VITE_WS_URL=wss://mithraic.space/ws +VITE_MEDIA_URL=https://mithraic.space/media +VITE_PROXY_URL=https://mithraic.space/proxy +EOF +``` + +- [ ] **Step 2: Confirm build succeeds with these env vars** + +```bash +cd packages/client +pnpm build +``` + +Expected: `dist/` folder is created with no errors. + +- [ ] **Step 3: Commit** + +```bash +cd ../.. +git add packages/client/.env +git commit -m "chore: configure env for mithraic.space" +git push origin main +``` + +--- + +## Task 3: Fix the root layout in Interface.tsx + +**Files:** +- Modify: `packages/client/src/Interface.tsx` + +The current `Layout` uses `display: flex` with no explicit column widths, and `Content` uses `width: 100%` which doesn't fill remaining space properly in a flex context. The fix: switch Layout to CSS Grid with `auto 1fr` columns, and replace `width: 100%` on Content with `minWidth: 0` so it respects the grid. + +- [ ] **Step 1: Open `packages/client/src/Interface.tsx` and find the two styled components at the bottom of the file** + +They look like this: +```typescript +const Layout = styled("div", { + base: { + display: "flex", + height: "100%", + minWidth: 0, + }, + // ... +}); + +const Content = styled("div", { + base: { + background: "var(--md-sys-color-surface-container-low)", + display: "flex", + width: "100%", + minWidth: 0, + }, + // ... +}); +``` + +- [ ] **Step 2: Replace `Layout` base styles — switch from flex to grid** + +Change the `Layout` styled component's `base` to: +```typescript +const Layout = styled("div", { + base: { + display: "grid", + gridTemplateColumns: "auto 1fr", + height: "100%", + overflow: "hidden", + }, + variants: { + disconnected: { + true: { + color: "var(--md-sys-color-on-primary-container)", + background: "var(--md-sys-color-primary-container)", + }, + false: { + color: "var(--md-sys-color-outline)", + background: "var(--md-sys-color-surface-container-high)", + }, + }, + }, +}); +``` + +- [ ] **Step 3: Replace `Content` base styles — remove width:100%, add minWidth:0** + +```typescript +const Content = styled("div", { + base: { + background: "var(--md-sys-color-surface-container-low)", + display: "flex", + minWidth: 0, + overflow: "hidden", + }, + variants: { + sidebar: { + false: { + borderTopLeftRadius: "var(--borderRadius-lg)", + borderBottomLeftRadius: "var(--borderRadius-lg)", + overflow: "hidden", + }, + }, + }, +}); +``` + +- [ ] **Step 4: Start the dev server and verify the message area now fills the screen** + +```bash +cd packages/client && pnpm dev +``` + +Expected: The message area takes up the majority of the window. Sidebar stays on the left without overflowing. + +- [ ] **Step 5: Commit** + +```bash +cd ../.. +git add packages/client/src/Interface.tsx +git commit -m "fix: switch root layout to CSS Grid, message area fills remaining space" +git push origin main +``` + +--- + +## Task 4: Fix Sidebar panel widths + +**Files:** +- Modify: `packages/client/src/interface/Sidebar.tsx` + +The Sidebar wraps both the server icon list and the channel list in a single `display: flex` div. We need to give each child an explicit width so they never squeeze or overflow. + +- [ ] **Step 1: Open `packages/client/src/interface/Sidebar.tsx` and find the root return statement** + +It looks like: +```typescript +return ( +