9.4 KiB
9.4 KiB
STACK
Technology stack reference for the xtablo monorepo. Last updated 2026-05-14.
Languages & Runtimes
- TypeScript — pinned at
^5.7.0across most workspaces (api uses^5.8.3). Root devDependency inpackage.json. - Node.js —
>=20.0.0enforced via theenginesfield in the rootpackage.json. The API Dockerfile builds onnode:20-alpine(apps/api/Dockerfile). - Package manager — pnpm
10.19.0(declared aspackageManagerin the rootpackage.json). Cloudflare Workers builds and the API container usecorepackto install pnpm. - Go — a parallel
go-backend/service exists alongside the TS monorepo (go-backend/go.mod,go 1.26.0) usingchi,templ,pgx/v5, andsqlc. It is included in the pnpm workspace but is otherwise its own toolchain. - Python — a small infra utility at
infra/app/main.pywithinfra/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, withtw-animate-cssandtailwind-merge. - Radix UI + React Aria — primitives composed in
@xtablo/ui(seepackages/ui/package.json). - BlockNote — rich-text editor (
@blocknote/core,@blocknote/mantine,@blocknote/react) used inapps/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, plusexternal,clients,tablo-views). - react-day-picker — calendar UI.
- PWA —
vite-plugin-pwa+workbox-windowinapps/main.
Backend (Hono)
- Hono ^4.7.7 — HTTP framework for both
apps/apiandapps/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-workeruses Hono with aChatRoomSQLite-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 inapps/main,apps/clients,apps/admin,apps/external, and@xtablo/tablo-views.axios ^1.12.2— HTTP client wrapper atpackages/shared/src/lib/api.ts.
Client State
zustand ^5.0.5— global stores (notably user). Lives in@xtablo/sharedand is consumed viauseUser/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 viapackages/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 inapps/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 inapps/main/src/lib/rum.tsandapps/clients/src/lib/rum.ts.dd-trace ^5.74.0— APM tracer started at the top ofapps/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. Cachesdist/**andtsconfig.tsbuildinfo. - Biome
2.2.5— formatter + linter, config atbiome.jsonwith explicit per-packagefiles.includes. - Vite
^6.2.2with@vitejs/plugin-react ^4.3.4,vite-tsconfig-paths,@tailwindcss/vite,@cloudflare/vite-plugin,rollup-plugin-visualizer,vite-plugin-pwa. - Vitest —
^3.2.4in frontend apps,^4.0.8inapps/api. Browser env viahappy-dom(main, admin) orjsdom(clients). - Testing Library —
@testing-library/react,@testing-library/jest-dom,@testing-library/user-event. - tsc — every package has its own
tsconfig.jsonand runstsc -bortsc --noEmitfor typecheck. - Wrangler
^4.24.3— Cloudflare Workers CLI used bymain,external,admin,clients,chat-worker. - tsx
^4.7.1— dev runner for the API (pnpm devinvokestsx watch src/index.ts).
Configuration
Environment loading
- API:
dotenv.config({ path:.env.${NODE_ENV}})inapps/api/src/config.ts.createConfig(secrets)synthesizes a typedAppConfigfrom env + Google Secret Manager values. - Frontend: Vite
import.meta.env.*; modesdev,staging,productionselected viavite build --mode.
Secret loading
apps/api/src/secrets.tspulls all sensitive values fromprojects/xtablo/secrets/*/versions/latestusing@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;globalDependenciesinclude**/.env.*local.tsconfig.jsonper workspace; project references across packages.
Workspace Structure
pnpm-workspace.yaml defines:
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 — seepackages/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-generateddatabase.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.