Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,18 @@ app/ # Next.js App Router (all source code)
β”œβ”€β”€ api/chat/sse/ # SSE endpoint for real-time chat updates
β”œβ”€β”€ assets/ # Static assets (fonts, images)
β”œβ”€β”€ components/ # Shared React components (with co-located tests)
β”œβ”€β”€ config.ts # Site metadata, links, external usernames
β”œβ”€β”€ health/ # Health check endpoint for monitoring
β”œβ”€β”€ lib/ # Utility libraries and core logic
β”‚ └── discord/ # Discord API and Gateway integration
β”‚ └── discord/ # Discord API, Gateway, and bot integration
β”œβ”€β”€ listening/[[...period]]/ # Listening stats page (optional catch-all)
β”‚ └── components/ # Route-specific components
β”œβ”€β”€ layout.tsx # Root layout
β”œβ”€β”€ page.tsx # Home page
β”œβ”€β”€ global-error.tsx # Global error boundary
└── global-not-found.tsx # Global 404 page

instrumentation.ts # Server startup hooks (bot subscription)
mocks/ # Test mocks (MSW handlers, env vars)
```

Expand All @@ -72,9 +74,19 @@ mocks/ # Test mocks (MSW handlers, env vars)
- `@/*` β†’ `app/*`
- `@/mocks/*` β†’ `mocks/*`

### Next.js Config

Key settings in `next.config.ts`:

- `output: "standalone"` β€” self-contained build for Docker deployment
- `cacheComponents: true` β€” Next.js 16 Cache Components
- `reactCompiler: true` β€” React Compiler (auto-memoization)
- `typedRoutes: true` β€” type-safe `<Link>` hrefs
- `experimental: { globalNotFound: true }` β€” top-level 404 page

### Typed Routes

`typedRoutes` is enabled for type-safe `<Link>` hrefs. For optional catch-all routes like `[[...param]]`, use a trailing slash to link to the base path (e.g., `/listening/` not `/listening`).
For optional catch-all routes like `[[...param]]`, use a trailing slash to link to the base path (e.g., `/listening/` not `/listening`).

### Environment Variables

Expand All @@ -101,6 +113,7 @@ Set `SKIP_ENV_VALIDATION=true` to skip validation (used in CI/Docker).
- **Gateway** (`app/lib/discord/gateway.ts`): WebSocket for real-time notifications with auto-reconnect and heartbeat
- **SSE** (`app/api/chat/sse/route.ts`): Streams chat updates to clients
- DataLoader with LRU cache (100 entries) batches user info requests
- Rate limit "gate" system prevents retry storms when Discord returns 429s
- Messages from site use "username: content" prefix format for attribution

### WakaTime Integration
Expand All @@ -116,9 +129,10 @@ Set `SKIP_ENV_VALIDATION=true` to skip validation (used in CI/Docker).

### Anthropic Integration (simon-bot)

- `app/lib/anthropic.ts`: Claude Haiku 4.5 for chat responses
- Triggered by "simon-bot" mention (case-insensitive, word boundary: `/\bsimon[- ]?bot\b/i`)
- 5-second timeout, runs async via Next.js `after()` to avoid blocking
- `app/lib/anthropic.ts`: Claude Haiku 4.5 for chat responses with tool use (chat history, WakaTime, Last.fm)
- `app/lib/discord/bot.ts`: Bot logic β€” triggered by "simon-bot" mention (regex: `/\bsimon[- ]?bot\b/i`)
- Started at server boot via `instrumentation.ts` β†’ `startBotSubscription()` (long-lived Gateway WebSocket subscription, not per-request)
- 5-second timeout per API call, Redis-based message deduplication (60s TTL) across instances
- Responses posted as threaded Discord replies

## Patterns
Expand Down