Developer Overview
Architecture, tech stack, and integration patterns for developers building on ProBeya.
import { createTRPCClient, httpBatchLink } from "@trpc/client";
import type { AppRouter } from "@probeya/api";
import superjson from "superjson";
const trpc = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: "https://acme.probeya.com/api/trpc",
transformer: superjson,
headers: { Authorization: "Bearer probeya_sk_live_..." },
}),
],
});
// Full type safety — autocomplete from database to client
const actions = await trpc.actions.list.query({
boardId: "clx_board_packaging",
status: "open",
overdue: true,
});
ProBeya is a TypeScript monorepo with end-to-end type safety from PostgreSQL to the browser. If you are building an integration, contributing to the codebase, or self-hosting, this page explains the architecture decisions and how the pieces fit together.
Tech stack
| Layer | Technology | Why this choice |
|---|---|---|
| Runtime | Node.js 22 | Web and WebSocket production target, native ESM |
| Framework | Next.js 16 (App Router, React 19) | Server components, streaming, middleware for subdomain routing |
| API | tRPC v11 | End-to-end type safety without code generation |
| Database | PostgreSQL 16 + Drizzle ORM | RLS for multi-tenancy, JSONB for EAV values, Drizzle for type-safe SQL |
| Auth | Auth.js v5 (NextAuth) | Credentials + OIDC (Authentik, Azure AD), JWT sessions |
| Real-time | WebSocket + Redis pub/sub | Board collaboration, presence, live updates across instances |
| Cache/Pub-Sub | Redis 7 | Session caching, rate limiting, WS fan-out, cron locks |
| Storage | S3-compatible (MinIO for dev) | File attachments, evidence photos, export artifacts |
| MCP | @modelcontextprotocol/sdk 1.x | AI assistant integration via stdio and HTTP transports |
| i18n | next-intl 4.x | 13 languages (EN, FR, NL, DE, IT, ES, PT, RU, AR, ID, ZH, JA, KO) |
| UI | Tailwind CSS v4 + shadcn/ui + Radix | Design tokens, accessible primitives, composable components |
| Monorepo | Turborepo + pnpm 9 | Parallel builds, dependency-aware task graph, workspace protocol |
| Validation | Zod | Shared schemas between client and server |
Repository structure
probeya/
├── apps/
│ ├── web/ # Next.js 16 — main application (port 8000)
│ ├── ws/ # WebSocket server — real-time collaboration (port 8003)
│ ├── mcp/ # MCP server — AI assistant integration (stdio + HTTP)
│ ├── edge/ # Edge node server — offline-capable site deployments
│ ├── mintlify-docs/ # Developer documentation (you are here)
│ └── docusaurus-docs/ # Product documentation (guide.probeya.com)
├── packages/
│ ├── api/ # tRPC routers (150+ routers), business logic
│ ├── db/ # Drizzle schemas, migrations, seed scripts
│ ├── shared/ # Zod validators, constants, types
│ ├── ui/ # shadcn/ui components (Radix + Tailwind)
│ └── config/ # Shared TypeScript and ESLint config
├── docker/ # Docker Compose for local infrastructure
└── turbo.json # Turborepo task pipeline
Integration patterns: when to use what
Use when: You are integrating from a non-TypeScript environment, building a Zapier/n8n workflow, or calling ProBeya from a CI/CD pipeline.
# List overdue actions on the packaging board
curl https://acme.probeya.com/api/v1/actions?boardId=clx_board_1&overdue=true \
-H "Authorization: Bearer probeya_sk_live_..."
- Standard HTTP verbs (GET, POST, PATCH, DELETE)
- JSON request/response bodies
- Bearer token authentication
- Rate limited (1000 req/min per token)
- OpenAPI-compatible
Architecture: request lifecycle
Browser / API Client / AI Agent
|
| HTTPS (REST or tRPC) / stdio (MCP)
v
Next.js Middleware
| Subdomain → organizationId resolution
| Locale detection (13 languages)
v
tRPC Context (packages/api/src/trpc.ts)
| Auth verification (session JWT or API key)
| orgProcedure: transaction + SET LOCAL for RLS
v
tRPC Routers (packages/api/src/routers/)
| 150+ domain routers — actions, kpis, boards, etc.
| Zod input validation
| Business logic + audit trail
v
PostgreSQL 16 (via Drizzle ORM)
| RLS policies enforce tenant isolation
| JSONB values for EAV custom fields
| cuid2 primary keys
Every org-scoped request runs inside a database transaction with SET LOCAL app.current_org_id. This means even if a bug in application code forgets to filter by organizationId, the RLS policy prevents cross-tenant data leakage. This is defense-in-depth.
Key development commands
pnpm dev # Start all apps in parallel (web, ws, docs)
pnpm build # Production build
pnpm lint # ESLint across all packages
pnpm type-check # TypeScript strict mode verification
pnpm format # Prettier formatting
pnpm db:migrate # Apply the immutable, hash-verified migration journal
pnpm --filter @probeya/db apply-rls # Install reviewed SQL and canonical RLS
pnpm --filter @probeya/db check-rls # Fail-closed catalog verification
pnpm db:generate # Generate migration files
pnpm db:seed # Seed demo data (Acme Pharma org)
pnpm db:studio # Open Drizzle Studio (visual DB browser)
What to read next
Was this page helpful?