Pand Platform v0.1.1
GitHub ↗ Demo App ↗
Agent-Native Platform 34/34 Verified Tasks Web • Admin • iOS • Android

Build Full-Stack & Native Mobile Apps at Agent Speed

Pand is an end-to-end application platform engineered for both human developers and autonomous AI agents. Define an entity once—Pand generates your PostgreSQL schema, OpenAPI 3.1 microservice routes, gateway wiring, typed TypeScript/Swift/Kotlin SDKs, Next.js pages, SwiftUI screens, and Jetpack Compose views.

Single Source of Truth

Drizzle PostgreSQL tables → Zod schemas → OpenAPI 3.1 → TS, Swift & Kotlin SDKs with zero manual glue.

Deterministic Architecture

FNV-1a port hashing, per-service PG schemas, and HS256 gateway identity JWTs prevent integration drift.

13 Built-In MCP Tools

First-class Model Context Protocol server with destructive-operation guardrails and structured JSON outputs.

Single-Box Production

Deploy to any Ubuntu VPS with Caddy auto-TLS, Restic S3 backups, Prometheus, Loki, Tempo & Grafana.

⚡ 60-Second Quickstart

Install the workspace or run the pand CLI directly to scaffold a complete multi-service, multi-platform application:

# 1. Create a new Pand project with Web, Admin, iOS, and Android apps
pand new acme-cloud --web --admin --ios --android
cd acme-cloud

# 2. Add a microservice (automatically assigned deterministic port)
pand add service billing

# 3. Add a full-stack entity across DB, Service, SDK, Web, iOS, and Android
pand add entity subscription \
  --service billing \
  --fields "organizationId:uuid,plan:enum(free|pro|enterprise)=free,seats:int=1,active:boolean=true,renewsAt:datetime?" \
  --web --ios --android

# 4. Generate and apply SQL migrations (isolated in the "billing" PG schema)
pand db generate
pand db migrate

# 5. Generate TypeScript, Swift, and Kotlin SDKs from merged OpenAPI specs
pand sdk gen

# 6. Run the 5-stage verification pipeline
pand check

# 7. Start local dev stack (Postgres, Redis, MinIO, Services, Gateway, Web)
pand dev
Agent Mode (--json)

Every CLI command accepts --json and returns a deterministic JSON payload with status, filesCreated, migrationsApplied, or structured error diagnostics.

🌟 Official Demo Application — Todo Pand

Explore Todo Pand (todo-pand), a full-stack, multi-tenant task and project management workspace built from scratch on the Pand platform.

Full-Stack Contract Wiring

Drizzle PostgreSQL schemas, OpenAPI 3.1 microservice routes, and auto-generated TypeScript SDK clients with zero drift.

Multi-Tenant Row-Level Scoping

Every project and task is strictly isolated by ownerId via gateway-injected internal identity JWTs (c.get("actor")!.sub).

Guest Workspace & Sync

Seamless transition from anonymous browser localStorage to authenticated database accounts via POST /todos/import-guest.

Dynamic Admin Console

Reactive entity CRUD and Better Auth administrative user management powered by @pands/admin-ui.

Explore the Source Code

Clone, inspect, and run the complete demo app on GitHub: github.com/MehdiNosrati/todo-pand →

🏗️ Architecture & Core Invariants

Pand enforces five strict architectural contracts across all generated services and packages so neither humans nor AI agents can introduce configuration drift.

1. Deterministic Port Allocation

Services never hardcode port numbers. Every service name is hashed using 32-bit FNV-1a into one of 50 collision-checked slots in 4000..8900:

// Port formula in @pands/config:
// slot = fnv1a32(serviceName) % 50
// port = 4000 + slot * 100
import { resolveServicePort, allocateServicePorts } from "@pands/config";

const corePort = resolveServicePort("core");       // e.g. 6300
const billingPort = resolveServicePort("billing"); // e.g. 4700
// Fixed platform ports:
// Gateway: 3000 | Web: 3001 | Admin: 3002 | Postgres: 5432 | Redis: 6379

2. Gateway Routing & Internal Identity JWT

Clients only talk to @pands/gateway on port 3000. The gateway authenticates cookies, bearer tokens, or API keys, enforces sliding-window rate limits, and forwards requests to /api/v1/<service>/* with a short-lived (60s TTL) HS256-signed x-pand-identity JWT:

// Decoded x-pand-identity JWT payload verified by @pands/service:
interface PandIdentityPayload {
  sub: string;       // Authenticated user ID
  orgId?: string;    // Active organization / tenant ID
  roles: string[];   // Assigned RBAC roles
  scopes: string[];  // Granted API key or OAuth scopes
  iat: number;
  exp: number;       // iat + 60 seconds
}

3. Per-Service PostgreSQL Schema Isolation

All microservices share a single PostgreSQL cluster in development and single-box production, but each service is strictly isolated inside its own PostgreSQL schema (pgSchema(serviceName)) and tracks migrations in __drizzle_migrations_<service>. Cross-schema SQL joins are forbidden by convention and linted via pand check.

4. Standard Error Envelope

All services and the gateway return errors in a single canonical format:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request payload",
    "details": { "fieldErrors": { "email": ["Invalid email"] } },
    "requestId": "req_01J9Z8K2M4X8P"
  }
}

🧬 Field DSL Reference

When running pand add entity <name> --fields "..." or invoking the MCP pand_add_entity tool, Pand parses a concise field DSL and generates Drizzle columns, Zod validators, OpenAPI schemas, and native UI inputs.

# Syntax: name:type[?][!][=default]
#   ? = nullable / optional
#   ! = unique constraint
#   =val = default value
--fields "sku:string!,title:string,priceCents:int=0,status:enum(draft|active|archived)=draft,metadata:json?,publishedAt:datetime?"
DSL Type Drizzle Column (Postgres) Zod Schema TypeScript Swift (iOS) Kotlin (Android)
string varchar({ length: 255 }) z.string() string String String
text text() z.string() string String String
int integer() z.number().int() number Int Int
float doublePrecision() z.number() number Double Double
boolean boolean() z.boolean() boolean Bool Boolean
datetime timestamp({ withTimezone: true }) z.string().datetime() string String String
uuid uuid() z.string().uuid() string String String
json jsonb() z.record(z.unknown()) Record<string, unknown> [String: AnyCodable] Map<String, Any?>
enum(a|b|c) varchar({ length: 64 }) z.enum(["a", "b", "c"]) "a" | "b" | "c" enum { case a, b, c } enum class { A, B, C }

Every table automatically includes standardColumns(): id (UUIDv4 primary key), createdAt, and updatedAt.

⌨️ CLI Reference — Scaffolding, DB & SDK

The @pands/cli binary (pand) orchestrates the full lifecycle of a Pand workspace. Pass --json to any command for structured JSON output.

Command Flags Description
pand new <name> --web --admin --ios --android --box Scaffolds a complete Pand monorepo with pand.config.ts, services/core, packages/sdk, AGENTS.md, and .agents/skills/*.
pand add service <name> --json Creates services/<name> with its own PG schema, health/OpenAPI endpoints, Vitest suite, and registers it in pand.config.ts.
pand add entity <name> --service <svc> --fields <dsl> --web --ios --android Generates Drizzle schema, CRUD routes, integration tests, and optional Next.js, SwiftUI, and Jetpack Compose screens.

Database, SDK & Verification Commands

Command Flags Description
pand db generate --service <svc> Generates idempotent SQL migrations (CREATE SCHEMA IF NOT EXISTS / CREATE TABLE IF NOT EXISTS) per service.
pand db migrate --service <svc> Applies pending migrations for each service using its isolated __drizzle_migrations_<svc> table.
pand db seed --service <svc> Runs src/db/seed.ts for one or all services.
pand db reset --force Drops service schemas and re-runs migrations + seeds (blocked in production).
pand db studio --service <svc> Launches Drizzle Studio for inspecting service tables.
pand sdk gen --ts-only --ios --android Extracts OpenAPI 3.1 specs from all services, merges them, and compiles TS, Swift, and Kotlin SDKs.
pand check --json Runs the 5-stage verification gate: TypeScript typecheck, Biome lint, OpenAPI spec validation, SDK drift check, and Vitest test suite.
pand dev --no-docker Starts Docker dev infra (Postgres, Redis, MinIO), runs migrations, watches services for SDK hot-reload, and boots the gateway.

Box, Secrets, Deployment, Preview & Observability Commands

Command Flags Description
pand secret set <KEY=VAL> --env <dev|prod> Encrypts secrets with AES-256-GCM in .pand/secrets.<env>.enc using master key in ~/.pand/master.key. Also supports list and rm.
pand box init --host <ip> --user <u> --domain <d> Registers a single-box Ubuntu VPS in ~/.pand/boxes.json and generates infra/box Docker Compose + Caddyfile. Also supports list and status.
pand deploy --env prod --dry-run Runs pand check, builds container images, syncs encrypted secrets, runs DB migrations, and performs zero-downtime rollout.
pand pause / resume --box <name> Stops or restarts application containers on the target Box while preserving persistent volumes.
pand backup create --output <dir> Runs pg_dump + Restic snapshot to S3/R2/local storage. Also supports pand backup list and pand backup restore <id>.
pand preview create <branch> --ttl 24h Creates an isolated PostgreSQL database clone and ephemeral preview deployment at https://<branch>.preview.<domain>. Also supports list and destroy.
pand logs / metrics / traces / usage --service <svc> --since 1h Queries Loki structured logs, Prometheus golden-signal metrics (RPS, P95, error rate), Tempo distributed traces, and container/disk usage.
pand upgrade --target <ver> Upgrades all @pands/* dependencies and runs AST/config codemods.

📦 Core Packages API Reference

@pands/config

Configuration & Port Hashing

Defines and validates pand.config.ts and computes deterministic FNV-1a service ports.

import { defineConfig, loadPandConfig, resolveServicePort, allocateServicePorts } from "@pands/config";

export default defineConfig({
  name: "acme-cloud",
  pandVersion: "0.1.1",
  services: {
    core: { path: "services/core" },
    billing: { path: "services/billing" },
  },
  apps: {
    web: { path: "apps/web", framework: "nextjs" },
    admin: { path: "apps/admin", framework: "nextjs" },
    ios: { path: "ios", bundleId: "com.acme.cloud" },
    android: { path: "android", packageName: "com.acme.cloud" },
  },
  gateway: {
    port: 3000,
    corsOrigins: ["http://localhost:3001", "http://localhost:3002"],
    rateLimit: { windowMs: 60_000, max: 120 },
  },
});

@pands/service

Microservice Runtime & Auto-CRUD

Wraps @hono/zod-openapi with correlation IDs, structured request logging, Prometheus metrics, HS256 gateway identity verification, and one-line Drizzle CRUD route generation.

import { createService, defineEntity, registerCrudRoutes } from "@pands/service";
import { createServiceDb, standardColumns } from "@pands/db";
import { z } from "zod";

const { db, schema } = createServiceDb("billing");

export const invoices = schema.table("invoices", {
  ...standardColumns(),
  customerId: schema.uuid("customer_id").notNull(),
  amountCents: schema.integer("amount_cents").notNull(),
  status: schema.varchar("status", { length: 32 }).notNull().default("draft"),
});

export const invoiceEntity = defineEntity({
  name: "invoice",
  plural: "invoices",
  table: invoices,
  createSchema: z.object({
    customerId: z.string().uuid(),
    amountCents: z.number().int().nonnegative(),
    status: z.enum(["draft", "open", "paid", "void"]).default("draft"),
  }),
});

export const service = createService({
  name: "billing",
  version: "0.1.1",
  db,
  entities: [invoiceEntity],
});

// Registers GET /, POST /, GET /:id, PATCH /:id, DELETE /:id with cursor pagination & OpenAPI 3.1 metadata
registerCrudRoutes(service.app, invoiceEntity, db);

Every service automatically exposes GET /health, GET /ready, GET /metrics, GET /openapi.json, and GET /_meta.

@pands/gateway

Edge Reverse Proxy & Identity Signer

Routes /api/v1/<service>/* to downstream services, merges service OpenAPI specs at GET /api/v1/openapi.json, exposes entity metadata at GET /api/v1/_meta, and streams real-time Server-Sent Events at GET /api/v1/events/stream.

import { createGateway, signInternalIdentity, verifyInternalIdentity } from "@pands/gateway";

const gateway = createGateway({
  services: {
    core: { url: "http://localhost:6300" },
    billing: { url: "http://localhost:4700" },
  },
  internalSecret: process.env.PAND_INTERNAL_SECRET!,
  corsOrigins: ["http://localhost:3001"],
  rateLimit: { windowMs: 60_000, max: 200 },
  resolveSession: async (req) => auth.verifyRequest(req),
});

@pands/db

Per-Service Drizzle ORM & Multi-Tenancy

Provides per-service PostgreSQL schema builders, UUIDv4 + timestamp standard columns, cursor pagination helpers, and organization-scoped query wrappers.

import { createServiceDb, standardColumns, scopeToOrg, decodeCursor, encodeCursor } from "@pands/db";

const { db, pgSchema, close } = createServiceDb("core", process.env.DATABASE_URL);

// Multi-tenant row scoping helper:
const tenantFilter = scopeToOrg(projects.organizationId, ctx.var.identity?.orgId);
const rows = await db.select().from(projects).where(tenantFilter);

@pands/auth

Sessions, JWT, OAuth, API Keys & RBAC

Full authentication and authorization suite for Web (HttpOnly cookies) and Native Mobile (Bearer access + refresh tokens), with built-in PBKDF2 password hashing, OAuth state/code exchange, API key management, and role/permission guards.

import { createPandAuth, createAuthClient } from "@pands/auth";

// Server setup (mounts /register, /login, /logout, /refresh, /me, /api-keys)
export const auth = createPandAuth({
  secret: process.env.PAND_AUTH_SECRET!,
  accessTokenTtlSeconds: 900,
  refreshTokenTtlSeconds: 60 * 60 * 24 * 30,
});

// Universal client for Web & React Native / Mobile
const authClient = createAuthClient({ baseUrl: "http://localhost:3000/api/v1/auth" });
const session = await authClient.login({ email: "dev@acme.io", password: "correct-horse-battery" });

@pands/sdk-gen

OpenAPI 3.1 → TS, Swift & Kotlin Compiler

Merges per-service OpenAPI 3.1 documents and generates zero-dependency, strongly-typed clients for TypeScript, Swift, and Kotlin.

import { mergeOpenApiSpecs, generateTypeScriptSdk, generateSwiftSdk, generateKotlinSdk } from "@pands/sdk-gen";

const merged = mergeOpenApiSpecs([
  { serviceName: "core", spec: coreOpenApi },
  { serviceName: "billing", spec: billingOpenApi },
]);

const tsCode = generateTypeScriptSdk(merged);
const swiftCode = generateSwiftSdk(merged);
const kotlinCode = generateKotlinSdk(merged, "com.acme.pand.sdk");

🎨 UI Primitives, Admin Console & Mobile SDKs

@pands/ui & @pands/admin-ui

React Components & Auto-Admin

@pands/ui provides accessible, zero-configuration React components (Button, Input, Select, Badge, Card, Dialog, DataTable, AutoForm, ToastProvider). @pands/admin-ui introspects GET /api/v1/_meta to render a full CRUD Admin Console automatically.

import { DataTable, AutoForm, Button } from "@pands/ui";
import { AdminDashboard } from "@pands/admin-ui";

// Render an entire multi-service Admin Console with search, pagination, and Zod-backed create/edit modals:
export default function AdminPage() {
  return <AdminDashboard gatewayUrl="http://localhost:3000" />;
}

Native iOS (SwiftUI) & Android (Jetpack Compose)

Mobile SDKs & Scaffolding

When you run pand add entity task --service core --fields "title:string,done:boolean=false" --ios --android, Pand generates:

  • iOS (Swift 5.9 / SwiftUI): ios/Sources/PandSDK/PandSDK.swift with URLSession async/await methods, KeychainTokenStore with automatic 401 token refresh retry, and a complete SwiftUI List + Create Sheet View and @MainActor ObservableObject ViewModel.
  • Android (Kotlin / Jetpack Compose): android/pand-sdk/src/main/kotlin/.../PandSDK.kt with Kotlin Coroutines, SharedPreferencesTokenStore, automatic 401 refresh retry, and a Material 3 Compose screen + StateFlow ViewModel.
// Swift (iOS) generated usage:
let client = PandClient(
    baseURL: URL(string: "https://api.acme.io")!,
    tokenStore: KeychainTokenStore(service: "com.acme.app")
)
let tasks = try await client.coreListTasks(limit: 25)
let created = try await client.coreCreateTask(input: CreateTaskInput(title: "Ship v1", done: false))

⚙️ Platform Services — Events, Storage, Push, Analytics & Testing

@pands/events

BullMQ Event Bus & Cron Jobs

Typed domain events and background jobs backed by Redis + BullMQ in production and an instant in-memory bus in tests.

import { defineEvent, createEventBus } from "@pands/events";
import { z } from "zod";

export const InvoicePaid = defineEvent("billing.invoice.paid", z.object({
  invoiceId: z.string().uuid(),
  amountCents: z.number().int(),
}));

const bus = createEventBus({ driver: "memory" }); // or { driver: "bullmq", redisUrl: process.env.REDIS_URL }
bus.subscribe(InvoicePaid, async (payload) => {
  console.log("Invoice paid:", payload.invoiceId);
});
await bus.publish(InvoicePaid, { invoiceId: "550e8400-e29b-41d4-a716-446655440000", amountCents: 4900 });

@pands/storage

S3 / MinIO / Cloudflare R2 Object Storage
import { createStorageClient } from "@pands/storage";

const storage = createStorageClient({
  driver: "s3", // or "memory" for unit tests
  endpoint: process.env.S3_ENDPOINT,
  bucket: "acme-uploads",
  region: "auto",
  accessKeyId: process.env.S3_ACCESS_KEY_ID!,
  secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,
});

await storage.putObject("avatars/u1.png", imageBuffer, "image/png");
const uploadUrl = await storage.presignUpload("avatars/u2.png", { expiresInSeconds: 300 });

@pands/push & @pands/analytics

Mobile Push & Product Telemetry
import { createPushClient } from "@pands/push";
import { createAnalyticsClient } from "@pands/analytics";

const push = createPushClient({ driver: "expo", accessToken: process.env.EXPO_ACCESS_TOKEN });
await push.send({
  to: "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]",
  title: "Deployment Complete",
  body: "acme-cloud v0.1.1 is live.",
});

const analytics = createAnalyticsClient({ endpoint: "/api/v1/analytics/events", batchSize: 10 });
analytics.track("invoice_created", { amountCents: 9900 });
await analytics.flush();

@pands/logger, @pands/telemetry & @pands/testing

Observability & Integration Testing
import { createLogger } from "@pands/logger";
import { createMetricsRegistry } from "@pands/telemetry";
import { createTestContext, testService } from "@pands/testing";

const logger = createLogger({ service: "billing" });
logger.info({ invoiceId: "inv_123", apiKey: "secret" }, "Processed invoice"); // apiKey automatically "[REDACTED]"

// In Vitest integration tests:
const client = testService(service);
const res = await client.request("/invoices", {
  method: "POST",
  body: { customerId: "550e8400-e29b-41d4-a716-446655440000", amountCents: 2500 },
  identity: { sub: "user_1", roles: ["admin"], scopes: ["*"] },
});

🤖 Agent Layer & Model Context Protocol (@pands/mcp)

Pand includes a native MCP server (@pands/mcp) over stdio or in-process calls, giving AI coding agents 13 structured tools with built-in safety guardrails (blocking destructive database resets in production and enforcing secret redaction).

MCP Tool Name Description
pand_project_info Returns parsed pand.config.ts, allocated service ports, apps, and workspace topology.
pand_list_entities Lists all entities across all services along with their fields and API endpoints.
pand_add_service Scaffolds a new microservice and registers it in pand.config.ts.
pand_add_entity Scaffolds a full-stack entity across Drizzle, Hono OpenAPI, Web, iOS, and Android.
pand_db_generate Generates Drizzle SQL migrations for all or selected services.
pand_db_migrate Applies pending PostgreSQL migrations safely.
pand_sdk_gen Regenerates TypeScript, Swift, and Kotlin SDKs from live/static OpenAPI specs.
pand_check Runs the 5-stage verification suite and returns structured pass/fail diagnostics.
pand_logs Queries recent structured JSON logs filtered by service, level, or correlation ID.
pand_metrics Returns RPS, error rate, and latency percentiles per service.
pand_traces Fetches OpenTelemetry distributed traces across Gateway → Service → Postgres.
pand_deploy_status Inspects active Box deployments, container health, and preview environments.
pand_secret_list Lists configured secret keys (values are strictly redacted from agent context).

Built-In Agent Skills (skills/ & .agents/skills/)

Pand includes 6 agent skills in the repository root (skills/ and .agents/skills/) and automatically scaffolds them into every project created with pand new:

Skill Path Description
pand skills/pand/SKILL.md Master platform skill covering the CLI, Field DSL, all @pands/* packages, multi-tenancy, and Box deployment.
add-feature skills/add-feature/SKILL.md End-to-end runbook for scaffolding a full-stack feature across DB, API, SDK, Web, iOS, and Android.
add-endpoint skills/add-endpoint/SKILL.md How to author custom non-CRUD OpenAPI routes with @hono/zod-openapi and integration tests.
modify-schema skills/modify-schema/SKILL.md How to safely alter Drizzle tables, generate SQL migrations, and verify zero contract drift.
add-mobile-screen skills/add-mobile-screen/SKILL.md How to build or customize SwiftUI (iOS) and Jetpack Compose (Android) screens using PandSDK.
debug-production skills/debug-production/SKILL.md How to triage production errors via Loki logs, Tempo traces, Prometheus RED metrics, and read-only SQL.

🖥️ Single-Box Production Infrastructure & Monitoring

infra/box packages an entire production cloud onto a single Ubuntu VPS with automatic HTTPS via Caddy, daily encrypted Restic backups, and a pre-wired Grafana observability stack:

  • Caddy Reverse Proxy: Automatic Let's Encrypt TLS certificates for your primary domain and wildcard *.preview.<domain> branches.
  • Observability Stack: Prometheus (metrics scraping), Loki (log aggregation), Tempo (OTLP trace collector), Grafana (pre-provisioned golden-signal dashboards), and ntfy push notifications for high error rate or disk pressure alerts.
  • Automated Backups: pand backup create snapshots PostgreSQL and MinIO volumes via Restic with configurable retention policies (7 daily, 4 weekly, 6 monthly).