Files
kill-the-news/CLAUDE.md
T
2026-05-21 07:40:00 +02:00

92 lines
3.9 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Commands
```bash
npm install # Install dependencies
npm run dev # Start local dev server (wrangler dev)
npm test # Run tests once
npm run test:watch # Run tests in watch mode
npm run test:coverage # Run tests with coverage report
npm run build # Dry-run deploy bundle (wrangler deploy --dry-run)
npm run deploy # Deploy to Cloudflare production
npm run format # Format with Prettier
```
Run a single test file:
```bash
npx vitest run src/routes/admin.test.ts
```
## Architecture
Cloudflare Worker built with Hono. A single Worker handles three route groups:
- `POST /api/inbound` — ForwardEmail webhook; IP-restricted to ForwardEmail MX sources (verified dynamically via `https://forwardemail.net/ips/v4.json`, with in-memory cache + static fallback)
- `GET /rss/:feedId` — public RSS feed rendered from KV
- `/admin` — password-protected admin UI (server-rendered HTML with inline scripts)
### Key files
| File | Purpose |
| ----------------------- | ------------------------------------------------------------------------ |
| `src/index.ts` | App entrypoint: CORS middleware, IP allowlist middleware, route mounting |
| `src/routes/inbound.ts` | Email ingestion: validates, parses, stores to KV |
| `src/routes/rss.ts` | Reads KV and renders RSS XML |
| `src/routes/admin.ts` | Admin UI (HTML) and feed/email CRUD API |
| `src/types/index.ts` | Shared TypeScript types (`Env`, `FeedConfig`, `EmailData`, etc.) |
| `src/test/setup.ts` | Test mocks for KV (`MockKV`) and Cache; exports `createMockEnv()` |
### KV schema
All data lives in the `EMAIL_STORAGE` KV namespace:
| Key | Value |
| --------------------------- | ------------------------------------------------- |
| `feeds:list` | `{ feeds: Array<{ id, title, description? }> }` |
| `feed:<feedId>:config` | `FeedConfig` object |
| `feed:<feedId>:metadata` | `{ emails: Array<{ key, subject, receivedAt }> }` |
| `feed:<feedId>:<timestamp>` | Full `EmailData` object |
`src/utils/storage.ts` contains alternate key helpers not used by routes — keep route key usage consistent with the schema above.
### Admin UI architecture
The admin UI is server-rendered HTML returned by `src/routes/admin.ts`. Interactive behavior (toast notifications, clipboard, bulk delete, table column resizing/sorting) is implemented as inline scripts in `src/scripts/`. Styles are composed from `src/styles/`. These are bundled into the Worker — there is no separate frontend build step.
### Testing
Tests run in Node (not a Worker runtime). Hono test requests pass the mock env as the 3rd argument:
```ts
const res = await app.request("/path", init, createMockEnv());
```
MSW (`msw/node`) handles external HTTP mocks. Tests that hit validation paths intentionally produce stderr output — this is expected.
### Worker environment bindings (`Env`)
```ts
EMAIL_STORAGE: KVNamespace; // KV namespace for all data
ADMIN_PASSWORD: string; // Cloudflare Worker secret (not in wrangler.toml)
DOMAIN: string; // e.g. "yourdomain.com"
```
## Configuration
- `wrangler.toml` is generated locally from `wrangler-example.toml` by `setup.sh` — do not commit `wrangler.toml`
- `ADMIN_PASSWORD` is a Cloudflare Worker secret set via `wrangler secret put`; it is never in config files
- Keep `compatibility_date` current on runtime upgrades
## When changing behavior
Update these together:
- `README.md`
- `AGENTS.md`
- `setup.sh` (if setup/deploy assumptions changed)
- Tests under `src/routes/*.test.ts` and `src/test/setup.ts`