# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview `turboci-admin` is a Next.js (Pages Router) admin panel for TurboCI, a CI/CD deployment system. It manages deployments, services, and servers across cloud providers. ## Commands ### Development ```bash bun run project:init # Full first-time setup: install deps, init twui submodule, generate DB schema bun run dev # Next.js dev server on port 3772 (web only) bun run pm2:dev # Start all 3 processes (web + cron + websocket) via PM2 in dev/watch mode bun run pm2:start # Start all 3 processes via PM2 in production mode bun run pm2:kill # Kill all PM2 processes ``` ### Build & Database ```bash bun run build # Production Next.js build bun run db:schema # Regenerate SQLite types from schema (run after DB changes) ``` ### Docker ```bash bun run docker:start # Rebuild and start all containers bun run docker:logs # Tail Docker logs ``` ### Submodule (twui) ```bash bun run twui:update # Pull latest twui component library ``` ## Architecture ### Process Model The app runs as **three separate processes**, managed by PM2 (dev) or Docker Compose (prod): | Process | Entry Point | Description | |---|---|---| | `turboci-web` | Next.js (port 3772) | Pages Router app + API routes | | `turboci-websocket` | `src/websocket/index.ts` | Bun native WebSocket server (port from `WEB_SOCKET_PORT` env) | | `turboci-cron` | `src/cron/index.ts` | Polls every 30s (`AppData.CronInterval`) to check services | ### Database - **ORM**: `@moduletrace/nsqlite` — SQLite with Bun - **Config**: `nsqlite.config.js` — DB name `turboci-admin`, stored in `src/db/` - **Types**: Auto-generated in `src/db/types.ts` via `bun run db:schema` - **Tables**: `users`, `users_ports` ### Key Directories - `src/pages/` — Next.js pages and API routes (`/api/*`) - `src/websocket/` — Bun WebSocket server; events are dispatched via a switch in `socket-message.ts` - `src/cron/` — Background cron job (service health checks) - `src/functions/` — Business logic (auth, deployment users, pages, ttyd) - `src/utils/` — Utilities including SSH execution, config file access, port management - `src/components/` — React components organized by page - `src/types/index.ts` — All shared TypeScript types including `TCIConfig`, `WebSocketEvents`, `PagePropsType` - `src/data/app-data.ts` — Central constants (`AppData`): cookie names, port ranges, timeouts - `src/exports/client-exports.ts` — Re-exports from `@moduletrace/datasquirel` (use `_n` for number coercion, `EJSON` for WebSocket serialization) - `twui/` — Git submodule: internal Tailwind UI component library ### TurboCI Config Files (Runtime) The app reads deployment config from the host at runtime: - `/root/.turboci/.config/turboci.json` — Main deployment config (`TCIGlobalConfig` type) - `/root/.turboci/.ssh/turboci` — SSH private key for connecting to deployment servers - `/root/.turboci/deployment_id` — Current deployment identifier Use `grabDirNames()` (`src/utils/grab-dir-names.ts`) to get these paths, never hardcode them. ### WebSocket Event Flow Client sends EJSON-serialized `WebSocketDataType` → `socket-message.ts` dispatches by `event` field → handler in `src/websocket/events/`. Connected users tracked in `global.WEBSOCKET_CONNECTED_USERS_DATA`. ### Auth Cookie-based auth using `@moduletrace/datasquirel`. Cookie names are in `AppData` (`AuthCookieName`, `AuthCSRFCookieName`). Use `userAuth` (`src/utils/user-auth.ts`) in API routes and `getServerSideProps`. ### Environment Variables Required in `.env` (see `test.env` for reference keys): - `DSQL_ENCRYPTION_PASSWORD` / `DSQL_ENCRYPTION_SALT` — Used by datasquirel for auth token encryption - `PORT` — Web server port (default 3772) - `WEB_SOCKET_PORT` — WebSocket server port - `HOST` — Full host URL (e.g. `http://localhost:3772`)