vibe-stack (vibestackdev) — Prompts
Excerpt 1: supabase-auth-security.mdc (security constraint rule)
---
description: Supabase auth security — enforces getUser() over getSession() on the server
globs: ["**/app/**", "**/actions/**", "**/api/**", "**/lib/supabase/**", "**/middleware.*"]
alwaysApply: false
---
# Supabase Auth Security
## RULE 1: NEVER Use getSession() on the Server
SECURITY CRITICAL: `getSession()` reads the JWT from cookies without revalidating it.
A malicious user can craft a fake session token that `getSession()` will silently accept.
`getUser()` sends a request to Supabase Auth to revalidate the JWT — it is cryptographically secure.
✅ SECURE (always use on the server):
```typescript
const { data: { user }, error } = await supabase.auth.getUser()
if (error || !user) redirect('/login')
❌ INSECURE (never use in server code):
// VULNERABILITY: This does NOT verify the JWT with the auth server
const { data: { session } } = await supabase.auth.getSession()
RULE 2: Always Use @supabase/ssr, Never @supabase/auth-helpers
The @supabase/auth-helpers-nextjs package is DEPRECATED.
Always import from @supabase/ssr for cookie-based sessions.
**Prompting technique**: YAML frontmatter declares glob-based activation scope. Rule body uses ALL-CAPS LABELS (`SECURITY CRITICAL`, `RULE 1`, `RULE 2`) as emphasis markers. ✅/❌ code examples provide concrete correct/incorrect patterns. The security rationale is explained ("reads the JWT without revalidating it") to help the AI understand *why*, not just *what*.
---
## Excerpt 2: nextjs15-params.mdc (breaking-change constraint rule)
```markdown
---
description: Critical Next.js 15 breaking changes regarding async params and searchParams
globs: ["**/app/**/page.tsx", "**/app/**/layout.tsx", "**/app/**/route.ts"]
alwaysApply: false
---
# Next.js 15 Async Params (BREAKING CHANGE)
CRITICAL: In Next.js 15+, `params` and `searchParams` are ASYNC Promises.
This is a breaking change from Next.js 14. The AI MUST await them.
✅ CORRECT (Next.js 15):
```tsx
type PageProps = {
params: Promise<{ slug: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export default async function Page({ params, searchParams }: PageProps) {
const { slug } = await params;
const search = await searchParams;
}
❌ WRONG (outdated Next.js 14 pattern — will crash silently):
// DO NOT GENERATE THIS PATTERN
export default function Page({ params }: { params: { slug: string } }) {
const { slug } = params; // BREAKS: params is a Promise in Next.js 15
}
**Prompting technique**: "BREAKING CHANGE" in the heading and "CRITICAL" in the body signal urgency to the AI. The `// DO NOT GENERATE THIS PATTERN` comment inside the wrong code example is a direct negative instruction embedded in the example itself — a double-layer prohibiton (rule text + inline comment).
---
## Excerpt 3: CLAUDE.md Security Rules Section
```markdown
## SECURITY RULES — NEVER VIOLATE
<security_critical>
1. NEVER use `supabase.auth.getSession()` in server-side code (Server Components, Server Actions, Route Handlers, middleware). It reads the JWT from cookies WITHOUT verifying it — a forged token passes silently. ALWAYS use `supabase.auth.getUser()` which makes a verification call to the Supabase auth server.
2. NEVER import from `@supabase/auth-helpers-nextjs` — it is DEPRECATED. Always use `@supabase/ssr` for both `createBrowserClient` (client) and `createServerClient` (server).
3. NEVER put auth enforcement logic in `middleware.ts`. Middleware runs on Edge Runtime and cannot securely verify Supabase JWTs. Middleware should ONLY call `updateSession()` to refresh tokens.
</security_critical>
Prompting technique: XML-tagged security block (<security_critical>) provides additional context signal for the AI. Numbered NEVER/ALWAYS dichotomies. Parenthetical explanation of why each rule exists. Caps NEVER/ALWAYS are stronger than "do not" — they signal non-negotiable constraints.