Remove verbose case studies, sync system docs, and redundant examples. Add Vercel/Railway/GitHub CLI debugging instructions and direct DB access guide.
5.7 KiB
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
- Use
@tpmjs/uicomponents — never raw HTML<button>,<input>,<table>, etc. - No barrel exports — import directly:
@tpmjs/ui/Button/Button, not@tpmjs/ui - Module boundaries — apps import packages, never the reverse. UI has no deps on utils.
- Avoid
count()in API routes — usetake: limit + 1technique for pagination (Prisma cold start is slow in serverless) - All API routes need
export const runtime = 'nodejs'andexport const maxDuration = 60
Essential Commands
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
# 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)
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)
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 inspectshows lambda functions (λ) — if you only see static pages (○), API routes didn't deployvercel logsshows runtime errors, timeouts, and cold start issues
Railway (Database / Services)
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
- Identify the problem: Is it a build failure, runtime error, or timeout?
- Check CI first:
gh run listthengh run view <id> --log-failed - Check Vercel:
vercel inspect <url>to verify lambdas deployed,vercel logs <url>for runtime errors - Check database:
railway logsor connect directly withrailway connect postgres - Verify the fix: Push, watch CI with
gh run watch, thencurl 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):
# Reads connection from packages/db/.env or DATABASE_URL env var
pnpm --filter=@tpmjs/db db:studio
psql (raw SQL queries):
# 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):
# 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
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
pnpm changeset # Create changeset
pnpm changeset:version # Version packages
pnpm changeset:publish # Publish to npm
git push --follow-tags # Push with tags