tpmjs/CLAUDE.md
Ajax Davis ae0d5e37cf docs: rewrite CLAUDE.md — concise, focused on production debugging
Remove verbose case studies, sync system docs, and redundant examples.
Add Vercel/Railway/GitHub CLI debugging instructions and direct DB access guide.
2026-02-10 02:47:13 +10:00

144 lines
5.7 KiB
Markdown

## Project Overview
Turborepo monorepo. pnpm workspaces. Next.js 16 App Router (`apps/web`). PostgreSQL via Prisma (`packages/db`). Deployed on Vercel. Database on Neon (via Railway for some services).
## Architecture Rules
1. **Use `@tpmjs/ui` components** — never raw HTML `<button>`, `<input>`, `<table>`, etc.
2. **No barrel exports** — import directly: `@tpmjs/ui/Button/Button`, not `@tpmjs/ui`
3. **Module boundaries** — apps import packages, never the reverse. UI has no deps on utils.
4. **Avoid `count()` in API routes** — use `take: limit + 1` technique for pagination (Prisma cold start is slow in serverless)
5. **All API routes need** `export const runtime = 'nodejs'` and `export const maxDuration = 60`
## Essential Commands
```bash
pnpm install # Install deps
pnpm dev --filter=@tpmjs/web # Dev server
pnpm build # Build all
pnpm type-check # Type-check all
pnpm lint # Lint all
pnpm format # Biome format
pnpm --filter=@tpmjs/db db:generate # Regenerate Prisma client (after schema changes)
pnpm --filter=@tpmjs/db db:push # Push schema to DB (dev)
pnpm --filter=@tpmjs/db db:migrate # Create migration (prod)
pnpm --filter=@tpmjs/db db:studio # Prisma Studio GUI
```
## Git Hooks (Lefthook)
Pre-commit runs: format, lint, type-check. Pre-push runs: test. If hooks pass locally, CI will pass too.
## Vercel Build
Build command: `cd ../.. && pnpm install && pnpm --filter=@tpmjs/web... build` (the `...` suffix builds all workspace dependencies first).
## Debugging Production Issues
You have access to `gh`, `vercel`, and `railway` CLIs. **Always use these first** when debugging production problems rather than guessing at fixes.
### Verify Deployment Status
```bash
# Check what commit is live in production
curl -s https://tpmjs.com/api/health | jq .
# Compare with local commit
git log --oneline -1
```
The health endpoint returns `commitSha`, `commitMessage`, and `deploymentUrl`.
### GitHub Actions (CI)
```bash
gh run list --limit 10 # Recent runs
gh run view <run-id> --log-failed # See failure logs
gh run view <run-id> --job <job-id> --log # Specific job logs
gh run rerun <run-id> --failed # Rerun failed jobs
gh run watch # Watch current run
gh pr checks <pr-number> # Check status on a PR
```
### Vercel (Deployments)
```bash
vercel ls # List deployments
vercel inspect <deployment-url> # Build info + lambda list
vercel logs <deployment-url> # Runtime logs
vercel logs <deployment-url> --since 1h # Last hour of logs
vercel env ls # List env vars
```
Key things to check:
- `vercel inspect` shows lambda functions (λ) — if you only see static pages (○), API routes didn't deploy
- `vercel logs` shows runtime errors, timeouts, and cold start issues
### Railway (Database / Services)
```bash
railway status # Current project/environment
railway logs # Service logs
railway logs --deployment <id> # Specific deployment logs
railway variables # List env vars
railway connect postgres # Connect to DB directly
railway up # Deploy current directory
```
### Debugging Workflow
1. **Identify the problem**: Is it a build failure, runtime error, or timeout?
2. **Check CI first**: `gh run list` then `gh run view <id> --log-failed`
3. **Check Vercel**: `vercel inspect <url>` to verify lambdas deployed, `vercel logs <url>` for runtime errors
4. **Check database**: `railway logs` or connect directly with `railway connect postgres`
5. **Verify the fix**: Push, watch CI with `gh run watch`, then `curl https://tpmjs.com/api/health`
### Direct Database Access
The production database is Neon PostgreSQL. Connection strings are in `.env.local` (`DATABASE_URL` for pooled, `DATABASE_URL_UNPOOLED` for direct).
**Prisma Studio** (GUI for browsing/editing data):
```bash
# Reads connection from packages/db/.env or DATABASE_URL env var
pnpm --filter=@tpmjs/db db:studio
```
**psql** (raw SQL queries):
```bash
# Connect using the unpooled URL for direct access
psql "$DATABASE_URL_UNPOOLED"
# Common queries
SELECT count(*) FROM tools;
SELECT id, name, slug, quality_score, view_count FROM tools ORDER BY view_count DESC LIMIT 20;
SELECT * FROM stats_snapshots ORDER BY date DESC LIMIT 5;
SELECT * FROM sync_logs ORDER BY created_at DESC LIMIT 10;
SELECT * FROM page_views ORDER BY date DESC LIMIT 20;
```
**One-off Prisma scripts** (when you need Prisma's type safety):
```bash
# Run a .ts script against prod DB using tsx
cd packages/db && npx tsx scripts/my-script.ts
```
**Note:** Prisma reads `.env` from `packages/db/`, not the root. If `db:studio` can't connect, ensure `DATABASE_URL` is set there or exported in your shell.
### Manual Cron Triggers
```bash
curl -X POST https://tpmjs.com/api/sync/changes -H "Authorization: Bearer $CRON_SECRET"
curl -X POST https://tpmjs.com/api/sync/keyword -H "Authorization: Bearer $CRON_SECRET"
curl -X POST https://tpmjs.com/api/sync/metrics -H "Authorization: Bearer $CRON_SECRET"
curl -X POST https://tpmjs.com/api/sync/view-rollup -H "Authorization: Bearer $CRON_SECRET"
curl -X POST https://tpmjs.com/api/sync/stats-snapshot -H "Authorization: Bearer $CRON_SECRET"
```
## Publishing Packages
```bash
pnpm changeset # Create changeset
pnpm changeset:version # Version packages
pnpm changeset:publish # Publish to npm
git push --follow-tags # Push with tags
```