DOCS / DEVELOPMENT / LOCAL DEVELOPMENT

Local Development

Workspace-wide commands

CommandPurpose
bun installInstall every workspace's dependencies.
bun run checkFormat + format-check + lint. Run before pushing.
bun run testvitest run, repo-wide.
bun run typecheck Typecheck every workspace (packages/api-contract, apps/gateway, then apps/dashboard's own nuxt typecheck).
bun run fmt / bun run fmt:checkoxfmt, write or check-only.
bun run lintoxlint, type-aware.

Per-app filtering

bash
Authorization: Bearer lattice_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Root package.json defines gateway, dashboard, and docs as shorthands for the respective bun --filter.

Gateway (apps/gateway)

CommandPurpose
bun run devnitro dev, default :3001.
bun run build / previewnitro build / nitro preview.
bun run db:migrateApply pending Drizzle migrations.
bun run db:generateGenerate a new migration from schema changes.
bun run db:studioDrizzle Studio against the gateway's DB.
bun run generate-pepperPrint a fresh API_KEY_PEPPER.
bun run seed <name>Create an application + its first API key.
bun run seed-management-key <name>Mint a management API key.

Dashboard (apps/dashboard)

CommandPurpose
bun run devnuxt dev, default :3000.
bun run build / previewnuxt build / nuxt preview.
bun run typechecknuxt typecheck.
bun run db:migrateApply better-auth's schema migrations against the dashboard's own DB.
bun run db:studioDrizzle Studio against the dashboard's DB.

Running one app against a real gateway

The dashboard and gateway are independently runnable — you don't need both if you're only changing one. To iterate on the dashboard alone, point LATTICE_GATEWAY_URL at any running gateway (local or shared) and skip standing up a second Postgres database for gateway data.

CI order

text
type ProviderAdapter = {
  id: ProviderId;
  createChatCompletion(
    request: ChatCompletionRequest,
    ctx: ProviderRequestContext,
  ): Promise<ChatCompletionResponse>;
  streamChatCompletion(
    request: ChatCompletionRequest,
    ctx: ProviderRequestContext,
  ): AsyncGenerator<ChatCompletionChunk, void, void>;
};

type ProviderRequestContext = {
  apiKey?: string;
  providerModel: string;
  signal: AbortSignal;
};

Mirrors what bun run check plus bun run test do locally — running both before pushing catches everything CI will.

Git hooks (husky)

HookRuns
Pre-commitbun run stage → lint-staged: oxfmt + oxlint on staged *.{ts,vue,md,yml,json,css,html} files only.
Pre-pushbun run test (typecheck is intentionally commented out here — see Coding Standards).

Hooks are installed automatically by the prepare script the first time you run bun install.

Testing

See Testing for the full layout and how to run a subset.

Database work

See Database & Migrations for the Drizzle Kit workflow shared by both apps.

LATTICE — INTERNAL AI INFRASTRUCTURE
GITHUB © 2026