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

LayerTechnologyWhy this choice
RuntimeNode.js 22Web and WebSocket production target, native ESM
FrameworkNext.js 16 (App Router, React 19)Server components, streaming, middleware for subdomain routing
APItRPC v11End-to-end type safety without code generation
DatabasePostgreSQL 16 + Drizzle ORMRLS for multi-tenancy, JSONB for EAV values, Drizzle for type-safe SQL
AuthAuth.js v5 (NextAuth)Credentials + OIDC (Authentik, Azure AD), JWT sessions
Real-timeWebSocket + Redis pub/subBoard collaboration, presence, live updates across instances
Cache/Pub-SubRedis 7Session caching, rate limiting, WS fan-out, cron locks
StorageS3-compatible (MinIO for dev)File attachments, evidence photos, export artifacts
MCP@modelcontextprotocol/sdk 1.xAI assistant integration via stdio and HTTP transports
i18nnext-intl 4.x13 languages (EN, FR, NL, DE, IT, ES, PT, RU, AR, ID, ZH, JA, KO)
UITailwind CSS v4 + shadcn/ui + RadixDesign tokens, accessible primitives, composable components
MonorepoTurborepo + pnpm 9Parallel builds, dependency-aware task graph, workspace protocol
ValidationZodShared 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)