# Layonara Forge — Agent Handoff Document ## What Is This Layonara Forge is a purpose-built NWN (Neverwinter Nights) Development IDE that runs as a local web application in Docker. It lets contributors fork, clone, edit, build, and run a complete Layonara NWNX NWN server with zero native tooling — only Docker required. The project name was chosen during brainstorming: "Forge" evokes crafting/building in a fantasy context. ## Project Location - **Forge codebase**: `/home/jmg/dev/layonara/layonara-forge/` - **Design spec**: `/home/jmg/dev/docs/superpowers/specs/2026-04-20-layonara-forge-design.md` - **Implementation plans**: `/home/jmg/dev/docs/superpowers/plans/2026-04-20-forge-plan-{1..6}-*.md` - **Gitea integration plan**: See Cursor plan file `gitea_+_forge_integration_8e0df077.plan.md` - **Design context**: `.impeccable.md` at project root (personality: arcane, precise, deep) ## Architecture ``` Host Machine ├── Browser → localhost:3000 (Forge UI) ├── NWN Toolset → writes GFFs to modules/temp0/ ├── ~/layonara-workspace/ (repos, server data, config) └── Docker Socket Docker Network ├── layonara-forge (Node.js + React, serves UI, manages everything via Docker socket) ├── layonara-builder (ephemeral: nasher, nwn_script_comp, layonara_nwn, cmake, gcc) ├── layonara-nwserver (ghcr.io/plenarius/unified — NWN:EE + NWNX) └── layonara-mariadb (mariadb:10.11 — game database) ``` The Forge container manages sibling containers via the Docker socket (Portainer pattern). Contributors clone one repo, set two paths in `.env`, run `docker compose up`, and open a browser. ## Tech Stack - **Backend**: Node.js 20 + Express 5 + TypeScript (ES modules) - **Frontend**: React 19 + Vite 6 + Tailwind CSS 4 (utility classes unreliable — inline styles used for layout) - **Icons**: lucide-react (SVG icons throughout) - **Fonts**: Self-hosted variable fonts via @fontsource-variable (Manrope, Alegreya, JetBrains Mono) - **Code editor**: Monaco Editor with NWScript Monarch tokenizer - **NWScript LSP**: Forked `layonara/nwscript-ee-language-server` connected via `monaco-languageclient` WebSocket. Server patched for Forge compatibility (see LSP server patches below). - **Terminal**: xterm.js with child_process.spawn shell sessions - **Docker API**: dockerode - **Git**: simple-git (named import: `import { simpleGit } from "simple-git"`) - **Git provider**: Gitea at `https://gitea.layonara.com` (NOT GitHub — see Gitea section) - **Real-time**: WebSocket via ws library ## What's Built (55 commits + UI overhaul session) All 6 implementation plans are complete. The codebase compiles and both Docker images build successfully. A complete UI/UX overhaul was performed (see "UI/UX Overhaul" section below). ### Backend Services (`packages/backend/src/services/`) | Service | File | Purpose | | ------------ | ------------------------- | ------------------------------------------------------------------ | | WebSocket | `ws.service.ts` | Event broadcasting to all connected clients | | Workspace | `workspace.service.ts` | Directory structure management, forge.json config | | Docker | `docker.service.ts` | Container CRUD, image pulls, ephemeral container runs | | Build | `build.service.ts` | Module compile/pack, hot-reload, hak builds, NWNX builds | | Server | `server.service.ts` | NWN server stack lifecycle (start/stop/restart MariaDB + nwserver) | | Toolset | `toolset.service.ts` | temp0/ file watcher, GFF→JSON conversion, change management | | Editor | `editor.service.ts` | File CRUD, directory trees, workspace search | | Git | `git.service.ts` | Clone, pull, commit, push, diff, upstream polling | | Git Provider | `git-provider.service.ts` | Gitea API (fork, PR, token validation) | | Terminal | `terminal.service.ts` | Shell session management via child_process | | LSP | `lsp.service.ts` | NWScript language server process management | ### Backend Routes (`packages/backend/src/routes/`) | Route | Prefix | Endpoints | | --------- | ---------------- | ----------------------------------------------------------------- | | workspace | `/api/workspace` | GET /config, PUT /config, POST /init | | docker | `/api/docker` | containers, pull, start/stop/restart, logs | | build | `/api/build` | module/compile, module/pack, deploy, compile-single, haks, nwnx | | server | `/api/server` | status, start, stop, restart, generate-config, seed-db, sql | | toolset | `/api/toolset` | status, start, stop, changes, apply, apply-all, discard | | editor | `/api/editor` | tree, file CRUD, search, resref, tlk, 2da, gff-schema | | github | `/api/github` | validate-pat (actually Gitea token), fork, forks, pr, prs | | repos | `/api/repos` | clone, list (/), status (/:repo/status), pull, commit, push, diff | | terminal | `/api/terminal` | sessions CRUD | ### Frontend Pages (`packages/frontend/src/pages/`) | Page | Route | Purpose | | --------- | ----------- | ----------------------------------------------------------- | | Dashboard | `/` | Server status, repo summary, quick actions (3-column cards) | | Editor | `/editor` | Monaco editor with file explorer, tabs, GFF visual editors | | Build | `/build` | Module/hak/NWNX build sections with streaming output | | Server | `/server` | Controls, log viewer with filter, SQL console | | Toolset | `/toolset` | temp0/ watcher status, change table, diff viewer | | Repos | `/repos` | Git status cards, commit dialog, PR creation | | Settings | `/settings` | PAT, theme, editable paths, Docker images, shortcuts, reset | | Setup | `/setup` | 4-phase onboarding wizard with 10 steps | ### Special Features - **NWScript syntax highlighting**: Monarch tokenizer with keyword/type/comment/string/preprocessor rules - **SQL highlighting in NWScript strings**: Detects `NWNX_SQL_PrepareQuery()` calls, highlights SQL keywords in teal - **Resref auto-lookup**: Backend indexes all GFF JSON files, hover on resref strings shows the item/creature/area - **TLK preview**: Hover on integer literals shows the TLK string (handles 16777216 custom offset) - **2DA intellisense**: Parses 2da files, provides completion for `Get2DAString` calls - **Visual GFF editors**: Form-based editors for .uti, .utc, .are, .dlg, .utp, .utm JSON files - **Conventional commit enforcement**: Type dropdown (feat/fix/refactor/etc), rejects malformed messages - **Dark/light theme**: OKLCH CSS custom properties toggled via `light` class on root element ## UI/UX Overhaul (April 21, 2026 session) A complete design overhaul was performed using the [Impeccable](https://impeccable.style/) design skill system. The design context is documented in `.impeccable.md`. ### Design System **Personality**: Arcane, precise, deep — a craftsman's workbench. **Fonts** (all self-hosted via `@fontsource-variable`, no Google Fonts): - **Body/UI**: Manrope Variable — warm geometric sans - **Headings**: Alegreya Variable — calligraphic serif with manuscript roots - **Code/mono**: JetBrains Mono Variable **Color palette** (full OKLCH, 30+ tokens in `globals.css`): - Surfaces tinted toward amber (hue 65) — "warm darks, not cold ones" - 3-level depth: `--forge-bg` → `--forge-surface` → `--forge-surface-raised` - Accent: evolved gold `oklch(58% 0.155 65)` with hover and subtle variants - Semantic colors: success (forest green, hue 150), danger (brick red, hue 25), warning (golden, hue 80), info (steel blue, hue 230) - Each semantic color has base, bg, and border variants for both dark and light modes - Log panels: dedicated `--forge-log-bg` / `--forge-log-text` tokens **Icons**: lucide-react SVG icons throughout (Code2, Wrench, Hammer, Play, GitBranch, Settings, Sun/Moon, Terminal, etc.) **Type scale** (fixed rem for IDE density): - `--text-xs` (11px) through `--text-2xl` (28px), ~1.25 ratio ### What Changed **Foundation**: - Replaced Inter font with Manrope Variable, Baskerville with Alegreya Variable - Removed Google Fonts `` — all fonts bundled as npm deps - Full OKLCH palette replacing all hex values (~60 hard-coded colors replaced) - All Tailwind semantic color classes (`green-400`, `red-500/20`, etc.) replaced with forge tokens - Global CSS: scrollbar theming, selection color, input/button base styles, `:focus-visible` ring, `prefers-reduced-motion` **IDE Shell** (`IDELayout.tsx`): - Lucide SVG icons replacing Unicode emoji in nav rail - Removed 3px left border stripe (impeccable anti-pattern ban) - Sidebar only shows on `/editor` route (was showing on all pages) - All layout uses inline styles (Tailwind flex classes were not reliably applying) - Terminal toggle bar with Terminal/Chevron icons **All 8 pages rewritten** with consistent patterns: - Card containers: `--forge-surface` bg, `--forge-border`, `0.75rem` radius - Section headers: uppercase, `--text-xs`, icon + label - Buttons: accent primary, outline secondary, danger for destructive - Status badges: semantic colors with dots - All inline styles (Tailwind utility classes unreliable for layout in this project) **Setup wizard**: - 4-phase indicator (Environment → Authentication → Repositories → Finalize) with numbered circles + connecting lines, matching James's work app wizard pattern - Steps reordered: Workspace + NWN Home before Gitea Token - PathInput component with folder icon for path fields - StatusDot component replacing emoji (✅❌⏳) with styled HTML elements - Navigation: ghost "← Back" left, accent "Next →" right, border-top separator **Performance**: - Routes code-split via `React.lazy()` — 10 chunks instead of 1 (760KB → initial 15KB app shell) - Page chunks: Editor 98KB, Setup 16KB, Repos 13KB, others 5-8KB each **Accessibility**: - `:focus-visible` outline on all interactive elements - `aria-label="Main navigation"` on nav - Tab close button changed from `` to `