For use with TendSocial and related projects
The Prime Directive
Implement the INTENT, not the WORDS.
When given technical requirements, your job is to:
- Understand the business goal behind the requirement
- Research the CURRENT best practice to achieve that goal
- Challenge outdated approaches before implementing
- Implement using current, stable, documented patterns
If requirements reference deprecated APIs, outdated patterns, or old library versions, you MUST:
- Stop and flag the discrepancy
- Explain what has changed
- Propose the modern equivalent
- Get approval before proceeding
Version Policy: Latest Stable Always
Mandatory Version Requirements
| Technology | Minimum Version | Notes |
|---|---|---|
| Node.js | 20.19+ | Required for Prisma v7 ESM support |
| TypeScript | 5.4+ | ESM compatibility |
| Prisma ORM | 7.x | ESM-native, no Rust engine |
| Fastify | 5.x | Current stable branch |
| React | 19.x | Current stable |
Before ANY Implementation
# ALWAYS check current versions before coding
npm info [package] version
npm info [package] versions --json | tail -20Never assume version compatibility from memory or past projects.
Breaking Changes Registry
This section documents critical API changes that frequently cause issues when developers (human or AI) pattern-match from old code.
Prisma ORM: Middleware → Client Extensions
REMOVED in v6.14, mandatory in v7:
// ❌ DOES NOT EXIST - Will fail silently or error
prisma.$use(async (params, next) => {
// This API was removed
return next(params)
})
// ✅ CORRECT - Use Client Extensions
const prisma = new PrismaClient().$extends({
query: {
$allModels: {
async $allOperations({ model, operation, args, query }) {
// Your logic here
return query(args)
}
}
}
})Multi-tenant isolation (the RIGHT way in v7):
// backend/src/db/prisma.extensions.ts
import { Prisma, PrismaClient } from './generated/prisma/client'
// Tenant isolation extension
export const createTenantClient = (companyId: string) => {
const baseClient = new PrismaClient()
return baseClient.$extends({
query: {
// Apply to all tenant-scoped models
post: {
async findMany({ args, query }) {
args.where = { ...args.where, companyId }
return query(args)
},
async findFirst({ args, query }) {
args.where = { ...args.where, companyId }
return query(args)
},
async create({ args, query }) {
args.data = { ...args.data, companyId }
return query(args)
},
async update({ args, query }) {
args.where = { ...args.where, companyId }
return query(args)
},
async delete({ args, query }) {
args.where = { ...args.where, companyId }
return query(args)
}
},
// Repeat for: image, campaign, etc.
}
})
}Prisma v7: ESM & Driver Adapters
Prisma v7 is ESM-only and uses driver adapters:
// backend/src/db/client.ts
import 'dotenv/config' // MUST be first import
import { PrismaClient } from './generated/prisma/client'
import { PrismaPg } from '@prisma/adapter-pg'
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL
})
export const prisma = new PrismaClient({ adapter })Required package.json:
{
"type": "module"
}Required tsconfig.json:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "Node",
"target": "ES2023",
"esModuleInterop": true
}
}Required schema.prisma:
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}Strict Typing & Validation
We enforce strict TypeScript and runtime validation.
Core Rules
NO
anyorunknown- Prohibited:
data: any,input: unknown(unless immediately refined) - Required: Explicit interfaces or Zod inferred types
- Why:
anydefeats the purpose of TypeScript;unknownrequires noisy type guards everywhere.
- Prohibited:
Zod for Runtime Validation
- ALL API inputs must be validated with Zod
- NO generic schemas like
z.record(z.unknown()) - Required: Strict schemas that match the TypeScript interfaces
Examples
❌ PROHIBITED:
// Lazy typing
const generatePost = (input: any) => { ... }
// Lazy validation
const schema = z.object({
settings: z.record(z.unknown())
})✅ REQUIRED:
// Explicit typing
interface GenerationInput {
topic: string;
settings: FrontmatterSettings;
}
// Strict Validation
const schema = z.object({
topic: z.string(),
settings: z.object({
includeTitle: z.boolean(),
tags: z.array(z.string())
})
})Error Handling Types
When handling errors in catch blocks (which are always unknown in strict TS), use our helper guards:
import { isError, getErrorMessage } from '@/types/common.js';
try {
// ...
} catch (error: unknown) {
// ✅ Correctly handle unknown error type
logger.error(getErrorMessage(error));
if (isError(error)) {
// error is now typed as Error
return error.message;
}
}Tech Stack Reference
Backend (Cloud Run)
| Component | Technology | Current Pattern |
|---|---|---|
| Framework | Fastify v5 | Plugin architecture, ESM imports |
| ORM | Prisma v7 | Client extensions, driver adapters |
| Validation | Zod + @fastify/type-provider-zod | Schema-first validation |
| Auth | Supabase Auth (verify JWTs) | Extract companyId from token |
Frontend (Vercel)
| Component | Technology | Notes |
|---|---|---|
| Framework | Next.js 15+ | App Router |
| Auth | Supabase Auth | Google/MS OAuth |
| State | React Query / Zustand | As needed |
Infrastructure
| Service | Purpose | Connection |
|---|---|---|
| Neon | PostgreSQL | DATABASE_URL via GCP Secret Manager |
| Cloud Run | Backend hosting | 0.0.0.0:$PORT |
| Supabase | Auth only | SUPABASE_URL, SUPABASE_ANON_KEY |
| Cloudflare R2 | Object storage | R2_* keys via Secret Manager |
| Sentry | Monitoring | DSN in both frontend/backend |
The Challenge Protocol
When you receive requirements that seem to reference outdated patterns, STOP and challenge.
Required Challenge Format
🚨 IMPLEMENTATION CONFLICT DETECTED
Requirement states: "[exact requirement text]"
This references [deprecated feature/old pattern] which was
[removed/deprecated] in [library] v[version].
Modern equivalent:
- [Current approach name]
- [Brief description]
- [Link to official docs]
Recommended implementation:
[Code snippet or approach]
Please confirm before I proceed.Examples of When to Challenge
| If you see... | Challenge with... |
|---|---|
| "Prisma middleware" | Client extensions (removed in v6.14) |
prisma.$use() | prisma.$extends() pattern |
| CommonJS requires | ESM imports (Prisma v7 requirement) |
prisma-client-js generator | prisma-client generator |
| Missing driver adapter | PrismaPg adapter setup |
| Fastify v4 patterns | Check v5 migration guide |
File Naming & Structure
backend/
├── src/
│ ├── generated/
│ │ └── prisma/ # Prisma client output
│ ├── db/
│ │ ├── client.ts # Base Prisma client setup
│ │ └── extensions/
│ │ ├── tenant.ts # Multi-tenant isolation
│ │ └── audit.ts # Audit logging
│ ├── modules/
│ │ └── [feature]/
│ │ ├── routes.ts
│ │ ├── handlers.ts
│ │ ├── schemas.ts # Zod schemas
│ │ └── service.ts
│ ├── middleware/
│ │ └── auth.ts # JWT verification, companyId extraction
│ └── index.ts
├── prisma/
│ ├── schema.prisma
│ └── seed.ts
├── package.json # "type": "module"
└── tsconfig.json # ESM configPre-Implementation Checklist
Before writing any code, verify:
- [ ] Checked pnpm for current stable versions of all dependencies
- [ ] Confirmed API patterns match current library versions
- [ ] Requirements don't reference deprecated/removed features
- [ ] ESM compatibility verified (no CommonJS patterns)
- [ ] Environment variables match expected names in docs
AI Agent-Specific Instructions
You Are Not a Code Completion Tool
You are a senior developer. When given requirements:
- Parse intent - What business problem are we solving?
- Verify approach - Is the suggested implementation current?
- Challenge if needed - Outdated patterns waste everyone's time
- Implement correctly - Use current stable patterns
Never Do This
- Implement deprecated APIs because "that's what the requirement said"
- Assume library versions from training data
- Copy patterns from old projects without verification
- Stay silent when you detect version conflicts
Always Do This
- Check official docs for current patterns
- Ask for clarification on ambiguous requirements
- Propose alternatives when requirements are outdated
- Document any significant deviations with reasoning
Quick Reference: Common Gotchas
| Wrong | Right | Why |
|---|---|---|
prisma.$use() | prisma.$extends() | Middleware removed in v6.14 |
require('...') | import ... from '...' | Prisma v7 is ESM-only |
"type": "commonjs" | "type": "module" | Prisma v7 requirement |
prisma-client-js | prisma-client | New generator name |
| No driver adapter | PrismaPg adapter | Required for v7 |
fastify.listen(3000) | fastify.listen({ port, host }) | Object syntax in v5 |
Appendix: Official Documentation Links
Last updated: January 2026Stack: Prisma v7 / Fastify v5 / Node 20+ / TypeScript 5.4+