Full-stack edge stack
This page documents the traveler-labs/core operator stack. Cursor rules under .cursor/rules/ mirror this policy for AI-assisted development.
Layout
Section titled “Layout”| Layer | Location | Notes |
|---|---|---|
| Admin UI | apps/admin | Vite + React + TanStack Query |
| Storefront | apps/web | Next.js (separate repo slice when present) |
| Docs | apps/docs | Astro Starlight (this site) |
| API Worker | workers/esim-api | Hono on Cloudflare Workers |
| Jobs Worker | workers/esim-jobs | Queue consumers |
| Platform DB | packages/db-kit | Identity / tenant tables |
| Product DB | packages/db-esim | eSIM domain tables + drizzle-zod |
| Shared schemas | packages/schemas | Route/body Zod for API edges |
| Admin shell | packages/admin-shell | Layout, ProtectedRoute, DataTable |
Request path (API)
Section titled “Request path (API)”route → handler → service → repository → db- Routes wire HTTP paths and middleware only.
- Handlers validate input (Zod /
@hono/zod-validator) and map JSON responses. - Services orchestrate use-cases; repositories own Drizzle queries.
Hono RPC
Section titled “Hono RPC”Every Worker API exports its RPC type at the entry:
export type AppType = typeof app;Admin UI consumes it via:
import { createHonoRpcClient } from "@core-labs/api-client-kit/hono-client";import type { EsimApiType } from "@traveler-labs/esim-api/rpc";
const client = createHonoRpcClient<EsimApiType>(baseUrl, { token });const res = await client.api.v1.admin.dashboard.$get();Implementation lives in apps/admin/src/lib/rpc-admin.ts. Auth endpoints (/auth/login, OTP) stay on plain fetch because they run before a session exists.
Auth & RBAC
Section titled “Auth & RBAC”- Operator login: email OTP → JWT (
/api/v1/auth/login,/auth/otp/verify). Super admins may receive an instant token. - Admin gate:
adminAuthMiddlewareon/admin/*— Bearer JWT or legacyX-Internal-Api-Key. - Role checks:
requireAdminRoles('super_admin')on sensitive mutations (settings secrets, partner create, market create/update). - Client guard:
ProtectedRoutevalidates/admin/mebefore rendering the shell (no layout flash).
Drizzle + drizzle-zod (SSOT)
Section titled “Drizzle + drizzle-zod (SSOT)”| Package | Zod export path | Scope |
|---|---|---|
@core-labs/db-kit | ./schema/zod | Identity / users |
@traveler-labs/db-esim | ./schema/zod | Markets, products, orders, partners, campaigns |
Derive insert/select schemas with drizzle-zod; extend with .pick() / .extend() for API DTOs in @traveler-labs/schemas when the HTTP shape differs from the table row.
Frontend data fetching
Section titled “Frontend data fetching”- Wrap the app in
QueryClientProvider(apps/admin/src/main.tsx). - Reads:
useQueryhooks inapps/admin/src/lib/queries/. - Mutations:
useMutationhooks inapps/admin/src/lib/mutations/. - Prefer RPC helpers over hand-rolled
fetchfor/admin/*.
Cloudflare bindings (esim-api)
Section titled “Cloudflare bindings (esim-api)”| Binding | Resource | Purpose |
|---|---|---|
DB | core-d1 | D1 SQLite |
R2_PRIVATE | core-r2 | Private uploads (POST/GET /admin/uploads) |
KV_CONFIG | core-kv-config | Operator settings + email templates |
KV_OTP | core-kv-otp | Admin OTP codes |
QUEUE_* | q-esim-* | Async jobs (issue, notify, sync, …) |
Production deploy is CI only (path-filtered deploy-*.yml + scripts/preflight-cloudflare.mjs). PR verify is .github/workflows/ci.yml (typecheck / lint / test / db:verify:local / OpenAPI). Local dev: wrangler dev -c wrangler.prod.toml --local.
Admin JWT is Worker secret AUTH_SECRET (not the template name JWT_SECRET).
UI tokens
Section titled “UI tokens”Admin surfaces use @core-labs/admin-shell shadcn CSS variables (bg-background, text-foreground, bg-primary, …). Do not hardcode Tailwind palette classes or hex values in product pages.
Related Cursor rules
Section titled “Related Cursor rules”80-fullstack-edge-stack.mdc— stack overview (always applied in core)21-typescript-vite-react.mdc— Vite admin conventions25-admin-ui-design-system.mdc— admin-shell component policy30-api-hono-zod.mdc— Hono + Zod + RPC export