Skip to content

For use with TendSocial and related projects

The Prime Directive

Implement the INTENT, not the WORDS.

When given technical requirements, your job is to:

  1. Understand the business goal behind the requirement
  2. Research the CURRENT best practice to achieve that goal
  3. Challenge outdated approaches before implementing
  4. 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

TechnologyMinimum VersionNotes
Node.js20.19+Required for Prisma v7 ESM support
TypeScript5.4+ESM compatibility
Prisma ORM7.xESM-native, no Rust engine
Fastify5.xCurrent stable branch
React19.xCurrent stable

Before ANY Implementation

bash
# ALWAYS check current versions before coding
npm info [package] version
npm info [package] versions --json | tail -20

Never 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:

typescript
// ❌ 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):

typescript
// 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:

typescript
// 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:

json
{
  "type": "module"
}

Required tsconfig.json:

json
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "Node",
    "target": "ES2023",
    "esModuleInterop": true
  }
}

Required schema.prisma:

prisma
generator client {
  provider = "prisma-client"
  output   = "../src/generated/prisma"
}

Strict Typing & Validation

We enforce strict TypeScript and runtime validation.

Core Rules

  1. NO any or unknown

    • Prohibited: data: any, input: unknown (unless immediately refined)
    • Required: Explicit interfaces or Zod inferred types
    • Why: any defeats the purpose of TypeScript; unknown requires noisy type guards everywhere.
  2. 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:

typescript
// Lazy typing
const generatePost = (input: any) => { ... }

// Lazy validation
const schema = z.object({
  settings: z.record(z.unknown())
})

✅ REQUIRED:

typescript
// 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:

typescript
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)

ComponentTechnologyCurrent Pattern
FrameworkFastify v5Plugin architecture, ESM imports
ORMPrisma v7Client extensions, driver adapters
ValidationZod + @fastify/type-provider-zodSchema-first validation
AuthSupabase Auth (verify JWTs)Extract companyId from token

Frontend (Vercel)

ComponentTechnologyNotes
FrameworkNext.js 15+App Router
AuthSupabase AuthGoogle/MS OAuth
StateReact Query / ZustandAs needed

Infrastructure

ServicePurposeConnection
NeonPostgreSQLDATABASE_URL via GCP Secret Manager
Cloud RunBackend hosting0.0.0.0:$PORT
SupabaseAuth onlySUPABASE_URL, SUPABASE_ANON_KEY
Cloudflare R2Object storageR2_* keys via Secret Manager
SentryMonitoringDSN 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 requiresESM imports (Prisma v7 requirement)
prisma-client-js generatorprisma-client generator
Missing driver adapterPrismaPg adapter setup
Fastify v4 patternsCheck 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 config

Pre-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:

  1. Parse intent - What business problem are we solving?
  2. Verify approach - Is the suggested implementation current?
  3. Challenge if needed - Outdated patterns waste everyone's time
  4. 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

WrongRightWhy
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-jsprisma-clientNew generator name
No driver adapterPrismaPg adapterRequired for v7
fastify.listen(3000)fastify.listen({ port, host })Object syntax in v5


Last updated: January 2026Stack: Prisma v7 / Fastify v5 / Node 20+ / TypeScript 5.4+

TendSocial Documentation