2f66fff993ec8b07d40a8f4426070b2942cd6e60
Build & Push Docker Image / build (push) Failing after 1m18s
Policy: every direct dependency is now an exact pin; lockfile + --frozen-lockfile keep builds reproducible; save-exact=true enforced. Toolchain: - pnpm 10.26 -> 11.18 (lockfile migrated; supportedArchitectures moved to pnpm-workspace.yaml) - typescript 5.9 -> 7.0, vite 7 -> 8, @vitejs/plugin-react 5 -> 6 - esbuild override 0.27.3 -> 0.28.1 (closes GHSA-g7r4-m6w7-qqqr); added @esbuild/darwin-arm64 for local dev - orval 8.9 -> 8.23, regenerated clients Backend (prod image): - openid-client 5.7 -> 6.8 (rewritten OIDC flow in routes/auth.ts: discovery + functional API, PKCE/state, fetchUserInfo, buildEndSessionUrl) - pino 9 -> 10, pino-http 10 -> 11, thread-stream 3 -> 4 - zod 3.25 -> 4.4 (catalog; supported by drizzle-zod 0.8.3) - pg 8.20 -> 8.22; removed deprecated @types/bcryptjs Frontend: - react/react-dom 19.1.0 -> 19.2.8 (catalog pin lifted; expo note removed) - react-day-picker 9 -> 10 (table classname -> month_grid) - recharts 2 -> 3 (TooltipContentProps + DefaultLegendContentProps typing; safe keys) - react-resizable-panels 2 -> 4 (Group/Separator rename) - date-fns 3 -> 4, @hookform/resolvers 3 -> 5, lucide-react 0.545 -> 1.28 - all @radix-ui/*, tailwind, types, and remaining patch/minor deps bumped to latest Security/process: - overrides for body-parser >=2.3.0 (GHSA-v422-hmwv-36x6) + markdown-it/linkify-it/brace-expansion/fast-uri (dev tooling) - pnpm audit now reports 0 vulnerabilities (prod and full) - CI audit gate added to build.yaml; docs/dependency-policy.md; renovate.json - Dockerfile pins node:24.18.1-alpine and pnpm@11.18.0
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%