Next.js + Drizzle + Clerk Vertical Slice

End-to-end pattern from auth middleware to tenant-scoped Drizzle queries and server actions.

CopilotCursorKilo
AuthorNeexoCore
Updated
nextjsdrizzleclerk

Overview

One vertical slice for the saas-multi-tenant playbook: sign-in → scoped query → mutation → test.

1. Auth middleware (proxy.ts)

Protect routes with Clerk; public routes explicit.

2. Auth context helper

Resolve userId and orgId in server components and actions — single helper used everywhere.

3. Drizzle schema

Tables include orgId; indexes for tenant filters.

4. Scoped query

const rows = await db.select().from(widgets).where(eq(widgets.orgId, orgId))

Never query without org scope on tenant data.

5. Server action

Validate with Zod v4 (import { z } from "zod/v4"); re-check org membership before writes.

6. Tests

Playwright or integration test: user A cannot read user B's org data.

Validation

npm run lint
npm run build
npx drizzle-kit check

Raw content

Copy into your project — e.g. .instructions.md, .agent.md, or SKILL.md

## Overview

One vertical slice for the `saas-multi-tenant` playbook: sign-in → scoped query → mutation → test.

## 1. Auth middleware (`proxy.ts`)

Protect routes with Clerk; public routes explicit.

## 2. Auth context helper

Resolve `userId` and `orgId` in server components and actions — single helper used everywhere.

## 3. Drizzle schema

Tables include `orgId`; indexes for tenant filters.

## 4. Scoped query

```typescript
const rows = await db.select().from(widgets).where(eq(widgets.orgId, orgId))
```

Never query without org scope on tenant data.

## 5. Server action

Validate with Zod v4 (`import { z } from "zod/v4"`); re-check org membership before writes.

## 6. Tests

Playwright or integration test: user A cannot read user B's org data.

## Validation

```bash
npm run lint
npm run build
npx drizzle-kit check
```

Next steps

Matched by shared tags and category. Browse all instructions