Skip to content

Brisket Local Development

Brisket is a Next.js 16 + React 19 app with Turbopack, tRPC, ConnectRPC, Clerk, Tailwind, and shadcn UI. Local development runs against a real or mocked sirloin instance.

Prerequisites

  • Node 22+ (see CI: NODE_VERSION: "22" in .github/workflows/brisket.yml).
  • pnpm 10.26.0 (PNPM_VERSION in the workflow). Install with corepack enable && corepack prepare pnpm@10.26.0 --activate.
  • A running sirloin instance reachable at SIRLOIN_URL (default: local docker stack via make dev-up-d, or staging gRPC endpoint).

Setup

Terminal window
# from repo root
pnpm install
cp apps/brisket/.env.example apps/brisket/.env.local
# fill in secrets — see brisket-env.
pnpm --filter brisket dev

TODO(@marty): confirm 1Password vault item name for shared dev values.

pnpm dev runs next dev --turbopack on http://localhost:3000. The first request triggers an env-var validation pass via @t3-oss/env-nextjs; missing required vars throw a Zod aggregate error. Set SKIP_ENV_VALIDATION=1 to bypass only if you know what you’re doing.

Useful Scripts

From apps/brisket/package.json:

ScriptWhat it does
pnpm --filter brisket devTurbopack dev server.
pnpm --filter brisket buildProduction build (next build --turbopack).
pnpm --filter brisket startRun the production build locally.
pnpm --filter brisket previewbuild && start.
pnpm --filter brisket lint / lint:fixESLint (max-warnings 0).
pnpm --filter brisket typechecktsc --noEmit.
pnpm --filter brisket testVitest.
pnpm --filter brisket checklint && typecheck.
pnpm --filter brisket format:check / format:writePrettier.

Architecture Cheat-Sheet

apps/brisket/src/
app/ # App Router (pages, layouts, route handlers)
api/ # /api/health, /api/trpc/[trpc], /api/webhook/clerk
components/ # Reusable React components (shadcn-style)
features/ # Feature modules (checkout, character page, etc.)
server/
api/
root.ts # tRPC appRouter
trpc.ts # context, middlewares (tracing, metrics)
sirloin-api.ts # ConnectRPC clients for SirloinService + BillingService
grpc-headers.ts # Header builders / call-option helpers
routers/*.ts # tRPC routers
hooks/ # Custom hooks
lib/ # logger, posthog, helper-functions, metrics
trpc/ # client setup
styles/ # Tailwind globals
middleware.ts # Clerk middleware + open-redirect guard
env.js # @t3-oss/env-nextjs schema
stage.js # BRISKET_STAGE resolution
pkg/ # Shared packages, including generated proto clients (pkg/sirloin/v5/*)

Tailwind + shadcn

  • Tailwind v3, configured per-app (tailwind.config.*). Utility class lookup is fastest in editors with the Tailwind IntelliSense extension.
  • shadcn UI components live in src/components/ui/ and are vendored — edit them in place. Re-running the shadcn CLI overwrites the local copy, so prefer manual edits and PR review.
  • Radix primitives are imported individually (@radix-ui/react-*) and composed into shadcn wrappers.
  • Framer Motion for animations; Jotai for client state. Avoid mixing global state for things tRPC + React Query already cache.

Turbopack Quirks

next dev --turbopack and next build --turbopack are both enabled. Things that bit us:

  • Some webpack-only plugins (legacy next.config.js entries) silently no-op under Turbopack. Verify behavior in dev and build.
  • Hot reload occasionally drops a state slice on heavy edits; full reload (R in the terminal) fixes it.
  • After dependency bumps, clear .next/: rm -rf apps/brisket/.next before re-running dev to avoid stale module graphs.
  • Source maps in dev are eager — large files can add a perceptible compile delay on first hit.

Auth in Dev

@clerk/nextjs requires NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY + CLERK_SECRET_KEY to be from the same Clerk instance. The dev Clerk app accepts arbitrary email magic links for sign-in. The webhook (/api/webhook/clerk) only matters if you need to test PostHog account_created / logged_in capture; otherwise skip.

For local middleware testing, public routes are: /sign-in, /sign-up, /waitlist, /api/health, /api/webhook/clerk, /forgot-password, /verification, /.well-known. Everything else triggers auth.protect().

Mocking the Backend

Brisket has no built-in mock layer. Three viable strategies:

  1. Run sirloin locallymake dev-up-d from the repo root brings up the Docker stack including sirloin and round. Inside the compose network brisket talks to sirloin at SIRLOIN_URL=http://sirloin:50051 (gRPC; see docker-compose.yml). When running brisket outside Docker against the compose stack, set SIRLOIN_URL=http://localhost:50051.
  2. Point at staging sirloin — set SIRLOIN_URL=https://sirloin-staging.<host> and use staging Clerk/Chargebee credentials. Lowest friction; do not run destructive flows against staging.
  3. Stub at the tRPC layer — for unit tests, apps/brisket/src/server/api/tests/ shows the pattern (mock the Connect client returned by getSirloinApi / getBillingApi). For UI work, mock the React Query layer using @tanstack/react-query’s testing helpers.

Strapi (FAQ) and Intercom soft-fail when their env vars are absent. Chargebee/Stripe/Turnstile widgets render in degraded modes when their public keys are blank — fine for non-checkout work but checkout flows need real keys.

Conventions (from apps/brisket/CLAUDE.md)

  • Filename: kebab-case for files, PascalCase for component exports.
  • Component structure: Component.tsx + colocated Component.test.tsx + Component.stories.tsx (where applicable).
  • Tests run with Vitest; UI with Testing Library.
  • ESLint and Prettier are non-negotiable; run pnpm check before pushing.

Common Pitfalls

  • Editing a NEXT_PUBLIC_* value requires a dev-server restart; values are baked at startup.
  • Importing ~/env in a client component is fine — the t3 client schema is the safe surface. Importing server-only fields in client code fails the build.
  • React 19 + pnpm overrides: do not bump React without checking the pnpm.overrides in package.json.
  • Turbopack dev cannot use the next/script preload hints the way webpack did — verify third-party scripts (Chargebee, Cloudflare) load correctly after changes.

Anchors

  • Env: brisket-env · API: brisket-api · Errors: brisket-errors · Runbook: brisket-runbook · On-Call: brisket-oncall.
  • Standards: standards/auth-model, standards/security-model. Operations: operations/testing-strategy.