# 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 `