f851305d7881a1d72f1f012198790c555a7f1437
Build & Push Docker Image / build (push) Successful in 2m25s
ToolRate
Community platform for listing and rating developer/productivity tools by usefulness and usability.
Stack
- pnpm workspaces, Node.js 24, TypeScript 5.9
- API: Express 5 + express-session + connect-pg-simple
- DB: PostgreSQL + Drizzle ORM
- Validation: Zod (
zod/v4),drizzle-zod - API codegen: Orval (from OpenAPI spec)
- Build: esbuild (CJS bundle)
- Frontend: React 19 + Vite + TanStack Query + wouter + shadcn/ui + recharts
Packages
lib/api-spec— OpenAPI contract (source of truth)lib/api-zod— generated Zod schemas from the speclib/api-client-react— generated React Query hookslib/db— Drizzle schema + DB accessartifacts/api-server— Express backendartifacts/toolrate— React frontendartifacts/mockup-sandbox— component preview
Run & develop
pnpm --filter @workspace/api-server run dev— run the API serverpnpm --filter @workspace/toolrate run dev— run the frontendpnpm run typecheck— full typecheck across all packagespnpm run build— typecheck + build all packagespnpm --filter @workspace/api-spec run codegen— regenerate API hooks and Zod schemas from the OpenAPI specpnpm --filter @workspace/db run push— push DB schema changes (dev only)
Required env vars
DATABASE_URL— Postgres connection stringSESSION_SECRET— session signing secretVOTER_SECRET— secret for voter submissionsLOCAL_ADMIN_USERNAME/LOCAL_ADMIN_PASSWORD— local admin login
Auth
- Session-based auth (not JWT), sessions stored in Postgres via connect-pg-simple.
- Write operations (create/update/delete tools, submit ratings) require auth; reads are public.
- Login via local admin user (
LOCAL_ADMIN_*). Keycloak/OIDC support exists as an optional legacy path.
Where things live
lib/api-spec/openapi.yaml— source of truth for the API contractlib/db/src/schema/— Drizzle table definitions (tools.ts,ratings.ts)lib/api-client-react/src/generated/— generated React Query hooks (do not edit)lib/api-zod/src/generated/— generated Zod schemas (do not edit)artifacts/api-server/src/routes/— Express route handlersartifacts/api-server/src/middleware/auth.ts—requireAuthmiddlewareartifacts/api-server/src/routes/auth.ts— login/logout/meartifacts/toolrate/src/pages/— frontend pagesartifacts/toolrate/src/components/— shared components (layout, tool-card, category-combobox, feature-input)artifacts/toolrate/src/hooks/use-auth.ts— auth state hook
Architecture decisions
- Contract-first: OpenAPI spec → codegen → typed hooks + Zod schemas. Never hand-write fetch calls.
- Session-based auth (not JWT) — sessions stored in Postgres via connect-pg-simple.
- Write operations (create/update/delete tools, submit votes) require auth. Reads are public.
- Category and feature autocomplete are client-side filtered against live API data (no separate index).
- Grafana can consume
/api/analytics/*endpoints directly via the JSON datasource plugin.
Product
- Browse and search tools by category, with ratings (usefulness 1-5 + usability 1-5)
- Submit new tools with features and tags
- Rate tools with comment and reviewer name
- Analytics dashboard: top tools chart, category breakdown, score distribution histograms
- Grafana integration: all
/api/analytics/*endpoints return clean JSON
Deployment
- Container image:
git.kubebase.de/admin/tool-evaluator:<tag>(pushed by CI) - Deployed to k3s via the
appsrepo (kustomize), served athttps://toolr.kubebase.de
Gotchas
- Orval clears the output folder during codegen — transient HMR errors in the dev server are normal and auto-recover.
- Auth uses PKCE — the
code_verifieris stored in the session, not in-memory state.
Description
Languages
TypeScript
95%
CSS
2.2%
JavaScript
2%
HTML
0.6%
Dockerfile
0.2%