# STACK Technology stack reference for the xtablo monorepo. Last updated 2026-05-14. ## Languages & Runtimes - **TypeScript** — pinned at `^5.7.0` across most workspaces (api uses `^5.8.3`). Root devDependency in `package.json`. - **Node.js** — `>=20.0.0` enforced via the `engines` field in the root `package.json`. The API Dockerfile builds on `node:20-alpine` (`apps/api/Dockerfile`). - **Package manager** — pnpm `10.19.0` (declared as `packageManager` in the root `package.json`). Cloudflare Workers builds and the API container use `corepack` to install pnpm. - **Go** — a parallel `go-backend/` service exists alongside the TS monorepo (`go-backend/go.mod`, `go 1.26.0`) using `chi`, `templ`, `pgx/v5`, and `sqlc`. It is included in the pnpm workspace but is otherwise its own toolchain. - **Python** — a small infra utility at `infra/app/main.py` with `infra/requirements.txt` (not part of the runtime stack of the apps). ## Frameworks ### Frontend (React) - **React 19.0.0** + **React DOM 19.0.0** — used by `apps/main`, `apps/external`, `apps/admin`, `apps/clients`, and all React packages. - **React Router** — `react-router-dom ^7.9.4`. - **Vite 6.2** — bundler/dev server for every web app (`apps/main/vite.config.ts`, `apps/external/vite.config.ts`, `apps/admin/vite.config.ts`, `apps/clients/vite.config.ts`). - **TailwindCSS 4.1** — utility CSS via `@tailwindcss/vite`, with `tw-animate-css` and `tailwind-merge`. - **Radix UI** + **React Aria** — primitives composed in `@xtablo/ui` (see `packages/ui/package.json`). - **BlockNote** — rich-text editor (`@blocknote/core`, `@blocknote/mantine`, `@blocknote/react`) used in `apps/main`. - **AG Grid Community** — data grid in `apps/main` (`ag-grid-community`, `ag-grid-react`). - **React Hook Form** + **Zod** — forms and validation, wired through `@hookform/resolvers`. - **i18next** + `react-i18next` — translations (`apps/main/src/i18n.ts`, plus `external`, `clients`, `tablo-views`). - **react-day-picker** — calendar UI. - **PWA** — `vite-plugin-pwa` + `workbox-window` in `apps/main`. ### Backend (Hono) - **Hono ^4.7.7** — HTTP framework for both `apps/api` and `apps/chat-worker`. - **@hono/node-server** — Node adapter that drives `apps/api` (`apps/api/src/index.ts`). - **hono-sessions** — session helpers in the API. - **Cloudflare Workers + Durable Objects** — `apps/chat-worker` uses Hono with a `ChatRoom` SQLite-backed DO class (`apps/chat-worker/wrangler.toml`, `apps/chat-worker/src/durable-objects/ChatRoom.ts`). ## Core Dependencies ### Server State / Data Fetching - `@tanstack/react-query ^5.69.0` — primary server-state cache. Hierarchical query keys; 5-minute default cache. Used in `apps/main`, `apps/clients`, `apps/admin`, `apps/external`, and `@xtablo/tablo-views`. - `axios ^1.12.2` — HTTP client wrapper at `packages/shared/src/lib/api.ts`. ### Client State - `zustand ^5.0.5` — global stores (notably user). Lives in `@xtablo/shared` and is consumed via `useUser` / `useMaybeUser`. ### Auth & JWT - `@supabase/supabase-js ^2.49.x` — front-end and API client. - `jwt-decode ^4.0.0` — decode access tokens on the client. - `jose ^6.0.0` — JWT verification in the chat worker (`apps/chat-worker/src/lib/auth.ts`). ### UI Primitives - Radix: `react-avatar`, `react-checkbox`, `react-collapsible`, `react-dialog`, `react-dropdown-menu`, `react-label`, `react-popover`, `react-select`, `react-separator`, `react-slider`, `react-slot`, `react-switch`, `react-tabs`, `react-tooltip`, `react-radio-group` (`packages/ui/package.json`). - `react-aria` / `react-aria-components ^1.7.0`, `@react-stately/*`, `@react-aria/*`. - `lucide-react ^0.460.0` — iconography. - `class-variance-authority`, `clsx`, `tailwind-merge` — class composition. - `sonner ^2.0.7` — toast notifications (re-exported via `packages/shared/src/lib/toast.ts`). ### Dates, IDs, Utilities - `date-fns ^4.1.0`, `luxon ^3.7.2` (API only), `@internationalized/date`. - `uuid ^11.1.0`, `pluralize ^8.0.0`, `ts-pattern ^5.6.2`. - `jspdf ^3.0.3` — PDF export (main + shared). ### Payments / Billing - `stripe ^20.0.0` — server SDK (`apps/api`). - `@stripe/stripe-js ^8.2.0` — browser SDK (`apps/main`). - `@supabase/stripe-sync-engine ^0.45.0` — Stripe ↔ Supabase sync (`apps/api/src/middlewares/stripeSync.ts`). ### Storage / Email - `@aws-sdk/client-s3 ^3.850.0` — used against Cloudflare R2 in `apps/api/src/middlewares/middleware.ts` (`r2Middleware`). - `multer ^2.0.2`, `sharp ^0.34.5` — file upload handling and image processing. - `nodemailer ^7.0.4` + `googleapis ^161.0.0` — Gmail OAuth2 SMTP (`apps/api/src/middlewares/transporter.ts`). ### Observability - `@datadog/browser-rum ^6.13.0` + `@datadog/browser-rum-react ^6.13.0` — initialised in `apps/main/src/lib/rum.ts` and `apps/clients/src/lib/rum.ts`. - `dd-trace ^5.74.0` — APM tracer started at the top of `apps/api/src/index.ts`. - `@datadog/datadog-ci`, `@datadog/datadog-ci-base`, `@datadog/datadog-ci-plugin-cloud-run` — CI source-map upload and Cloud Run integration. - `static-analysis.datadog.yml` — repo-level Datadog static analysis config. ## Build / Dev Tooling - **Turborepo `^2.5.8`** — pipeline orchestration (`turbo.json`). Tasks: `build`, `dev`, `deploy(:staging|:prod)`, `build:staging`, `build:prod`, `lint`, `lint:fix`, `typecheck`, `test`, `test:watch`, `format`, `clean`. Caches `dist/**` and `tsconfig.tsbuildinfo`. - **Biome `2.2.5`** — formatter + linter, config at `biome.json` with explicit per-package `files.includes`. - **Vite `^6.2.2`** with `@vitejs/plugin-react ^4.3.4`, `vite-tsconfig-paths`, `@tailwindcss/vite`, `@cloudflare/vite-plugin`, `rollup-plugin-visualizer`, `vite-plugin-pwa`. - **Vitest** — `^3.2.4` in frontend apps, `^4.0.8` in `apps/api`. Browser env via `happy-dom` (main, admin) or `jsdom` (clients). - **Testing Library** — `@testing-library/react`, `@testing-library/jest-dom`, `@testing-library/user-event`. - **tsc** — every package has its own `tsconfig.json` and runs `tsc -b` or `tsc --noEmit` for typecheck. - **Wrangler `^4.24.3`** — Cloudflare Workers CLI used by `main`, `external`, `admin`, `clients`, `chat-worker`. - **tsx `^4.7.1`** — dev runner for the API (`pnpm dev` invokes `tsx watch src/index.ts`). ## Configuration ### Environment loading - API: `dotenv.config({ path: `.env.${NODE_ENV}` })` in `apps/api/src/config.ts`. `createConfig(secrets)` synthesizes a typed `AppConfig` from env + Google Secret Manager values. - Frontend: Vite `import.meta.env.*`; modes `dev`, `staging`, `production` selected via `vite build --mode`. ### Secret loading - `apps/api/src/secrets.ts` pulls all sensitive values from `projects/xtablo/secrets/*/versions/latest` using `@google-cloud/secret-manager`. - Test mode bypasses Secret Manager and uses raw env vars. ### Build targets per app | App | Bundler | Output | Deploy target | | --- | --- | --- | --- | | `apps/main` | Vite + `@cloudflare/vite-plugin` | `dist/` + worker | Cloudflare Workers (`apps/main/wrangler.toml`, routes `app.xtablo.com`, `app-staging.xtablo.com`) | | `apps/external` | Vite + Cloudflare plugin | `dist/` | Cloudflare Workers (`apps/external/wrangler.toml`) | | `apps/admin` | Vite + Cloudflare plugin | `dist/` | Cloudflare Workers (`apps/admin/wrangler.toml`) | | `apps/clients` | Vite + Cloudflare plugin | `dist/` | Cloudflare Workers (`apps/clients/wrangler.toml`) | | `apps/chat-worker` | Wrangler-native | Worker bundle | Cloudflare Workers + Durable Objects, `chat.xtablo.com` | | `apps/api` | `tsc` → `dist/` | Node 20 container | Google Cloud Run (`apps/api/Dockerfile`, `apps/api/cloudbuild.yaml`) | | `go-backend` | `go build` | Binary | Separate (see `go-backend/justfile`) | ### Static configs - `biome.json` — single source of truth for formatting/linting scope. - `turbo.json` — task graph; `globalDependencies` include `**/.env.*local`. - `tsconfig.json` per workspace; project references across packages. ## Workspace Structure `pnpm-workspace.yaml` defines: ```yaml packages: - 'apps/*' - 'go-backend' - 'packages/*' ``` ### Apps (`apps/`) - `@xtablo/main` — authenticated dashboard (port 5173). - `@xtablo/external` — embeddable public booking widget (port 5174). - `@xtablo/clients` — read-only client portal (port 5175, `clients.xtablo.com`). - `@xtablo/admin` — internal admin app (port 5176). - `@xtablo/api` — Hono REST API (port 8080). - `@xtablo/chat-worker` — Cloudflare Worker hosting Durable-Object chat (`chat.xtablo.com`). ### Packages (`packages/`) - `@xtablo/shared` — React contexts, hooks, supabase wrapper, axios client, toast helper. **Source-only** (no build step; consumers import TS directly — see `packages/shared/package.json` `"main": "./src/index.ts"`). - `@xtablo/ui` — Radix + Tailwind + react-aria component library. **Source-only**. - `@xtablo/shared-types` — pure TS types including Supabase-generated `database.types.ts`. **Source-only**, zero runtime deps. - `@xtablo/auth-ui` — shared auth screens. **Source-only**. - `@xtablo/chat-ui` — chat UI components consumed by main, clients, tablo-views. **Source-only**. - `@xtablo/tablo-views` — tablo view components shared between main and clients. **Source-only**. All shared packages export `./src/*` directly, so Vite HMR / tsc project references pick up changes instantly without a build step. ### pnpm overrides Root `package.json` pins `form-data ^4.0.4` and `linkifyjs ^4.3.2`, plus a `packageExtensions` entry adding `zod` as a peer of `@hookform/resolvers`.