# Spike Discord-Gitea bridge bot. Syncs PRs, comments, and code reviews between a Gitea server (git.nose.space) and Discord. ## Architecture ``` src/ ├── server.tsx — HTTP server (webhook endpoint, health check, error log) ├── config.ts — Dev/prod environment config (DB paths, channel IDs, username mappings) ├── discord/ — Discord bot client, event listeners, slash commands ├── gitea/ — Gitea API calls, types, username conversion └── bridge/ — Wiring between Gitea and Discord (webhook handler, DB, Discord helpers) ``` Dependencies flow one way: `bridge/ → gitea/`, `bridge/ → discord/`. Neither `gitea/` nor `discord/` imports from the other. ## Libs Each directory with an `index.ts` barrel is a standalone lib. Read the lib's README for its public API — you don't need to read internals to use it. - **[gitea/](src/gitea/README.md)** — Pure Gitea API client and types. No side effects, no Discord, no DB. - **[discord/](src/discord/README.md)** — Discord bot client, events, slash commands. Hands off to bridge for Gitea integration. - **[bridge/](src/bridge/README.md)** — The glue. Webhook handler, Discord helpers, SQLite DB for ID mappings. **Import rules:** - External code imports from the barrel only: `import { handleGiteaWebhook } from "./bridge"` - Never reach into internal files: ~~`import { handleGiteaWebhook } from "./bridge/webhook-handler"`~~ - Internal files within a lib can import from each other freely This keeps AI context small. When working on code that uses a lib, only read the lib's README — not every internal file. ## Running - `bun run subdomain:dev` — Start with hot reload - `bun run subdomain:start` — Start for production - `bun test` — Run integration tests (requires Tailscale funnel + test env vars) ## Environment Variables - `DISCORD_TOKEN` — Discord bot token - `DISCORD_CLIENT_ID` — Discord application client ID - `GITEA_API_TOKEN` — Gitea API token - `DATA_DIR` — Data directory (prod only) - `NODE_ENV` — `production` or omit for dev - `PORT` — Server port (default 3000)