aeo-optimization
AI Engine Optimization - semantic triples, page templates, content clusters for AI citations
Next.js with Supabase and Drizzle ORM
$ npx -y skills add alinaqi/claude-bootstrap --skill supabase-nextjs --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/supabase-nextjsContext preview
The summary Claude sees to decide when to auto-load this skill.
Next.js with Supabase and Drizzle ORM
name: supabase-nextjs description: Next.js with Supabase and Drizzle ORM when-to-use: When building a Next.js app with Supabase backend user-invocable: false paths: ["src/app/**", "src/db/**", "supabase/**"] effort: medium
Next.js App Router patterns with Supabase Auth and Drizzle ORM.
**Sources:** [Supabase Next.js Guide](https://supabase.com/docs/guides/auth/server-side/nextjs) | [Drizzle + Supabase](https://supabase.com/docs/guides/database/drizzle)
---
**Drizzle for queries, Supabase for auth/storage, server components by default.**
Use Drizzle ORM for type-safe database access. Use Supabase client for auth, storage, and realtime. Prefer server components; use client components only when needed.
---
project/ ├── src/ │ ├── app/ │ │ ├── (auth)/ │ │ │ ├── login/page.tsx │ │ │ ├── signup/page.tsx │ │ │ └── callback/route.ts │ │ ├── (dashboard)/ │ │ │ └── page.tsx │ │ ├── api/ │ │ │ └── [...]/route.ts │ │ ├── layout.tsx │ │ └── page.tsx │ ├── components/ │ │ ├── auth/ │ │ └── ui/ │ ├── db/ │ │ ├── index.ts # Drizzle client │ │ ├── schema.ts # Schema definitions │ │ └── queries/ # Query functions │ ├── lib/ │ │ ├── supabase/ │ │ │ ├── client.ts # Browser client │ │ │ ├── server.ts # Server client │ │ │ └── middleware.ts # Auth middleware helper │ │ └── auth.ts # Auth helpers │ └── middleware.ts # Next.js middleware ├── supabase/ │ ├── migrations/ │ └── config.toml ├── drizzle.config.ts └── .env.local
---
npm install @supabase/supabase-js @supabase/ssr drizzle-orm postgres npm install -D drizzle-kit
# .env.local NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321 NEXT_PUBLIC_SUPABASE_ANON_KEY=<from supabase start> # Server-side only SUPABASE_SERVICE_ROLE_KEY=<from supabase start> DATABASE_URL=postgresql://postgres:postgres@localhost:54322/postgres
---
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './src/db/schema.ts',
out: './supabase/migrations',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL!,
},
schemaFilter: ['public'],
});import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema';
const client = postgres(process.env.DATABASE_URL!, {
prepare: false, // Required for Supabase connection pooling
});
export const db = drizzle(client, { schema });import {
pgTable,
uuid,
text,
timestamp,
boolean,
} from 'drizzle-orm/pg-core';
export const profiles = pgTable('profiles', {
id: uuid('id').primaryKey(), // References auth.users
email: text('email').notNull(),
name: text('name'),
avatarUrl: text('avatar_url'),
createdAt: timestamp('created_at').defaultNow().notNull(),
updatedAt: timestamp('updated_at').defaultNow().notNull(),
});
export const posts = pgTable('posts', {
id: uuid('id').primaryKey().defaultRandom(),
authorId: uuid('author_id').references(() => profiles.id).notNull(),
title: text('title').notNull(),
content: text('content'),
published: boolean('published').default(false),
createdAt: timestamp('created_at').defaultNow().notNull(),
});
// Type exports
export type Profile = typeof profiles.$inferSelect;
export type NewProfile = typeof profiles.$inferInsert;
export type Post = typeof posts.$inferSelect;
export type NewPost = typeof posts.$inferInsert;---
import { createBrowserClient } from '@supabase/ssr';
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
}import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';
export async function createClient() {
const cookieStore = await cookies();
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return cookieStore.getAll();
},
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
);
} catch {
// Called from Server Component - ignore
}
},
},
}
);
}import { createServerClient } from '@supabase/ssr';
import { NextResponse, type NextRequest } from 'next/server';
export async function updateSession(request: NextRequest) {
let supabaseResponse = NextResponse.next({ request });
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return request.cookies.getAll();
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value }) =>
request.cookies.set(name, value)
);
supabaseResponse = NextResponse.next({ request });
cookiesToSet.forEach(({ name, value, options }) =>
supabaseResponse.cookies.set(name, value, options)
);
},
},
}
);
// Refresh session
const { data: { user } } = await supabase.auth.getUser();
return { supabaseResponse, user };
}---
import { type NextRequest, NextResponse } from 'next/server';
impoTurn Claude Code into a self-reviewing, test-enforced engineering system that remembers context across sessions — then route work across 13 models from a single dashboard.
Repo: alinaqi/claude-bootstrap
AI Engine Optimization - semantic triples, page templates, content clusters for AI citations
Claude Code Agent Teams - default team-based development with strict TDD pipeline enforcement
Build AI agents with Pydantic AI (Python) and Claude SDK (Node.js)
Latest AI models reference - Claude, OpenAI, Gemini, Eleven Labs, Replicate
Android Kotlin development with Coroutines, Jetpack Compose, Hilt, and MockK testing