@folpe/loom 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +82 -16
  2. package/data/agents/backend/AGENT.md +35 -3
  3. package/data/agents/database/AGENT.md +16 -4
  4. package/data/agents/frontend/AGENT.md +39 -5
  5. package/data/agents/marketing/AGENT.md +19 -2
  6. package/data/agents/orchestrator/AGENT.md +3 -21
  7. package/data/agents/performance/AGENT.md +9 -2
  8. package/data/agents/review-qa/AGENT.md +7 -3
  9. package/data/agents/security/AGENT.md +10 -4
  10. package/data/agents/tests/AGENT.md +11 -2
  11. package/data/agents/ux-ui/AGENT.md +16 -3
  12. package/data/presets/api-backend.yaml +2 -11
  13. package/data/presets/chrome-extension.yaml +2 -11
  14. package/data/presets/cli-tool.yaml +2 -10
  15. package/data/presets/e-commerce.yaml +2 -14
  16. package/data/presets/expo-mobile.yaml +2 -12
  17. package/data/presets/fullstack-auth.yaml +2 -14
  18. package/data/presets/landing-page.yaml +2 -11
  19. package/data/presets/mvp-lean.yaml +2 -12
  20. package/data/presets/saas-default.yaml +5 -14
  21. package/data/presets/saas-full.yaml +58 -0
  22. package/data/skills/api-design/SKILL.md +43 -2
  23. package/data/skills/auth-rbac/SKILL.md +179 -0
  24. package/data/skills/better-auth-patterns/SKILL.md +212 -0
  25. package/data/skills/chrome-extension-patterns/SKILL.md +13 -6
  26. package/data/skills/cli-development/SKILL.md +11 -3
  27. package/data/skills/drizzle-patterns/SKILL.md +166 -0
  28. package/data/skills/env-validation/SKILL.md +142 -0
  29. package/data/skills/form-validation/SKILL.md +169 -0
  30. package/data/skills/hero-copywriting/SKILL.md +12 -4
  31. package/data/skills/i18n-patterns/SKILL.md +176 -0
  32. package/data/skills/layered-architecture/SKILL.md +131 -0
  33. package/data/skills/nextjs-conventions/SKILL.md +46 -7
  34. package/data/skills/react-native-patterns/SKILL.md +10 -8
  35. package/data/skills/react-query-patterns/SKILL.md +193 -0
  36. package/data/skills/resend-email/SKILL.md +181 -0
  37. package/data/skills/seo-optimization/SKILL.md +10 -2
  38. package/data/skills/server-actions-patterns/SKILL.md +156 -0
  39. package/data/skills/shadcn-ui/SKILL.md +46 -12
  40. package/data/skills/stripe-integration/SKILL.md +11 -3
  41. package/data/skills/supabase-patterns/SKILL.md +23 -6
  42. package/data/skills/table-pagination/SKILL.md +224 -0
  43. package/data/skills/tailwind-patterns/SKILL.md +12 -2
  44. package/data/skills/testing-patterns/SKILL.md +203 -0
  45. package/data/skills/ui-ux-guidelines/SKILL.md +10 -5
  46. package/dist/index.js +451 -122
  47. package/package.json +2 -1
@@ -27,26 +27,14 @@ constitution:
27
27
  - Payment security — never handle raw card data, always use Stripe Elements
28
28
  - SEO drives traffic — product pages must be indexable with structured data
29
29
  - Performance converts — every 100ms of load time impacts conversion rate
30
- stack:
31
- - Next.js 16+ (App Router)
32
- - React 19
33
- - TypeScript 5 (strict)
34
- - Tailwind CSS 4
35
- - ShadCN UI
36
- - Supabase (auth + database)
37
- - Stripe (payments)
38
- - Vercel (deployment)
39
30
  conventions:
40
31
  - Use Stripe Checkout or Payment Elements — never collect card details directly
41
32
  - Implement webhook handlers for Stripe events (payment success, refund, etc.)
42
33
  - Use ISR or SSG for product catalog pages for performance
43
34
  - Add JSON-LD structured data for products (price, availability, reviews)
44
35
  - Implement optimistic cart updates with server validation
45
- claudemd:
36
+ context:
46
37
  projectDescription: >
47
- This is an e-commerce application scaffolded with Loom. It includes product catalog, shopping
38
+ This is an e-commerce application. It includes product catalog, shopping
48
39
  cart, Stripe checkout, and transactional emails. The orchestrator coordinates the full agent
49
40
  team including marketing for copywriting and SEO.
50
- orchestratorRef: >
51
- The orchestrator agent (.claude/agents/orchestrator.md) is the main entry point. Always start
52
- by delegating to the orchestrator, which will route tasks to the appropriate specialized agent.
@@ -20,25 +20,15 @@ constitution:
20
20
  - Offline-first — the app must be usable without network connectivity
21
21
  - Battery conscious — minimize background tasks and network requests
22
22
  - Smooth animations — target 60fps, never block the JS thread
23
- stack:
24
- - Expo SDK 52+
25
- - React Native
26
- - TypeScript 5 (strict)
27
- - NativeWind (Tailwind for React Native)
28
- - Expo Router (file-based navigation)
29
- - Supabase (auth + database)
30
23
  conventions:
31
24
  - Use Expo Router for all navigation — file-based routing
32
25
  - Implement offline storage with async-storage or MMKV for critical data
33
26
  - Use expo-notifications for push notifications setup
34
27
  - Handle deep linking and universal links from the start
35
28
  - Test on both iOS and Android — never assume platform parity
36
- claudemd:
29
+ context:
37
30
  projectDescription: >
38
- This is a mobile application scaffolded with Loom using Expo and React Native. It uses
31
+ This is a mobile application using Expo and React Native. It uses
39
32
  NativeWind for styling and Expo Router for navigation. The orchestrator delegates mobile UI
40
33
  to the frontend agent, API integration to the backend agent, and native feature testing
41
34
  to the tests agent.
42
- orchestratorRef: >
43
- The orchestrator agent (.claude/agents/orchestrator.md) is the main entry point. Always start
44
- by delegating to the orchestrator, which will route tasks to the appropriate specialized agent.
@@ -23,26 +23,14 @@ constitution:
23
23
  - Least privilege — users and services get only the permissions they need
24
24
  - Defense in depth — middleware, RLS, and API validation work together
25
25
  - Session management — handle expiry, refresh, and revocation properly
26
- stack:
27
- - Next.js 16+ (App Router)
28
- - React 19
29
- - TypeScript 5 (strict)
30
- - Tailwind CSS 4
31
- - ShadCN UI
32
- - Supabase Auth (email, OAuth, magic link)
33
- - Supabase (database with RLS)
34
- - Vercel (deployment)
35
26
  conventions:
36
27
  - Use Supabase Auth for all authentication flows
37
28
  - Implement middleware for route protection and role checks
38
29
  - Enable Row Level Security on all tables — no exceptions
39
30
  - Use server-side session validation, never trust client-only auth state
40
31
  - Separate admin and user dashboards with distinct layouts
41
- claudemd:
32
+ context:
42
33
  projectDescription: >
43
- This is a fullstack SaaS with complete authentication scaffolded with Loom. It includes email,
34
+ This is a fullstack SaaS with complete authentication. It includes email,
44
35
  OAuth, and magic link flows via Supabase Auth, plus RBAC and admin dashboard. The orchestrator
45
36
  coordinates security, frontend, backend, and database agents for auth-related tasks.
46
- orchestratorRef: >
47
- The orchestrator agent (.claude/agents/orchestrator.md) is the main entry point. Always start
48
- by delegating to the orchestrator, which will route tasks to the appropriate specialized agent.
@@ -19,23 +19,14 @@ constitution:
19
19
  - Performance is UX — aim for perfect Lighthouse scores
20
20
  - Mobile-first responsive — design for small screens, enhance for large
21
21
  - Accessible by default — semantic HTML, ARIA, keyboard navigation
22
- stack:
23
- - Next.js 16+ (static export)
24
- - React 19
25
- - TypeScript 5 (strict)
26
- - Tailwind CSS 4
27
- - Vercel (deployment)
28
22
  conventions:
29
23
  - Use Server Components and static generation for maximum performance
30
24
  - Optimize all images with next/image and proper srcset
31
25
  - Implement structured data (JSON-LD) for SEO
32
26
  - Use CSS animations and transitions over JS-based animation libraries
33
27
  - Ensure all interactive elements have visible focus states
34
- claudemd:
28
+ context:
35
29
  projectDescription: >
36
- This is a landing page / marketing site scaffolded with Loom. It focuses on SEO, conversion
30
+ This is a landing page / marketing site. It focuses on SEO, conversion
37
31
  optimization, and fast loading. The orchestrator delegates visual tasks to the frontend and
38
32
  ux-ui agents, copywriting to marketing, and performance audits to the performance agent.
39
- orchestratorRef: >
40
- The orchestrator agent (.claude/agents/orchestrator.md) is the main entry point. Always start
41
- by delegating to the orchestrator, which will route tasks to the appropriate specialized agent.
@@ -15,24 +15,14 @@ constitution:
15
15
  - Iterate fast — build the simplest thing that works, then improve
16
16
  - Technical debt is acceptable — speed wins at the prototype stage
17
17
  - Validate assumptions — build to learn, not to last
18
- stack:
19
- - Next.js 16+ (App Router)
20
- - React 19
21
- - TypeScript 5 (strict)
22
- - Tailwind CSS 4
23
- - Supabase (auth + database)
24
- - Vercel (deployment)
25
18
  conventions:
26
19
  - Prefer inline styles and co-located logic over abstractions
27
20
  - Use Supabase client directly — skip custom API layers when possible
28
21
  - Minimal component hierarchy — flatten where you can
29
22
  - Skip extensive error handling — focus on happy path first
30
23
  - One file per feature when practical
31
- claudemd:
24
+ context:
32
25
  projectDescription: >
33
- This is a lean MVP scaffolded with Loom. Speed and iteration are prioritized over architecture.
26
+ This is a lean MVP. Speed and iteration are prioritized over architecture.
34
27
  The orchestrator coordinates a small team of frontend, backend, and database agents to ship
35
28
  features as fast as possible.
36
- orchestratorRef: >
37
- The orchestrator agent (.claude/agents/orchestrator.md) is the main entry point. Always start
38
- by delegating to the orchestrator, which will route tasks to the appropriate specialized agent.
@@ -1,4 +1,4 @@
1
- name: SaaS Default
1
+ name: SaaS Full
2
2
  description: Standard SaaS project preset with full agent team, Next.js conventions, and Tailwind patterns. Includes
3
3
  orchestrator-driven multi-agent workflow.
4
4
  agents:
@@ -20,31 +20,22 @@ skills:
20
20
  - shadcn-ui
21
21
  - api-design
22
22
  - ui-ux-guidelines
23
+ - stripe-integration
24
+ - seo-optimization
23
25
  constitution:
24
26
  principles:
25
27
  - Ship fast, iterate often — prefer working software over perfect plans
26
28
  - User-first design — every feature must solve a real user problem
27
29
  - Type safety everywhere — leverage TypeScript strict mode
28
30
  - Convention over configuration — follow established patterns
29
- stack:
30
- - Next.js 16+ (App Router)
31
- - React 19
32
- - TypeScript 5 (strict)
33
- - Tailwind CSS 4
34
- - ShadCN UI
35
- - Supabase (auth + database)
36
- - Vercel (deployment)
37
31
  conventions:
38
32
  - Use Server Components by default, Client Components only when needed
39
33
  - Server Actions for all mutations
40
34
  - Zod validation at API boundaries
41
35
  - Mobile-first responsive design
42
36
  - Semantic HTML with ARIA attributes for accessibility
43
- claudemd:
37
+ context:
44
38
  projectDescription: >
45
- This is a SaaS application scaffolded with Loom. It uses a multi-agent architecture where the orchestrator delegates
39
+ This is a SaaS application. It uses a multi-agent architecture where the orchestrator delegates
46
40
  tasks to specialized agents (frontend, backend, database, etc.). Each agent follows the conventions defined in the
47
41
  linked skills.
48
- orchestratorRef: >
49
- The orchestrator agent (.claude/agents/orchestrator.md) is the main entry point. Always start by delegating to the
50
- orchestrator, which will route tasks to the appropriate specialized agent.
@@ -0,0 +1,58 @@
1
+ name: SaaS Full
2
+ description: SaaS complet avec architecture en couches, auth RBAC, i18n, forms, testing, emails et Stripe. Batteries-included.
3
+ agents:
4
+ - orchestrator
5
+ - frontend
6
+ - backend
7
+ - database
8
+ - ux-ui
9
+ - tests
10
+ - review-qa
11
+ - security
12
+ - performance
13
+ - marketing
14
+ skills:
15
+ - nextjs-conventions
16
+ - tailwind-patterns
17
+ - shadcn-ui
18
+ - api-design
19
+ - supabase-patterns
20
+ - ui-ux-guidelines
21
+ - layered-architecture
22
+ - drizzle-patterns
23
+ - server-actions-patterns
24
+ - form-validation
25
+ - auth-rbac
26
+ - i18n-patterns
27
+ - testing-patterns
28
+ - resend-email
29
+ - react-query-patterns
30
+ - table-pagination
31
+ - env-validation
32
+ - better-auth-patterns
33
+ - stripe-integration
34
+ - hero-copywriting
35
+ - seo-optimization
36
+ constitution:
37
+ principles:
38
+ - Functional over OOP — pure functions, composition, immutability
39
+ - Strict layered architecture — Presentation → Facade → Service → DAL → Persistence
40
+ - Type safety everywhere — TypeScript strict, Zod validation at boundaries
41
+ - Ship fast, iterate often — working software over perfect plans
42
+ - Security by design — auth + RBAC + validation at every layer
43
+ conventions:
44
+ - RSC by default, "use client" only when strictly needed
45
+ - Server Actions for all mutations, DAL for all reads
46
+ - Zod dual validation (client + server)
47
+ - Facades between presentation and services
48
+ - CASL authorization at service layer
49
+ - next-intl for all user-facing strings
50
+ - Vitest with role-based test strategy (PUBLIC/USER/ADMIN)
51
+ - kebab-case for all new files
52
+ context:
53
+ projectDescription: >
54
+ This is a full-featured SaaS application. It follows a strict layered architecture
55
+ (Presentation → Facade → Service → DAL → Persistence) with multi-agent orchestration. Authentication is
56
+ handled by Better Auth with RBAC via CASL. The app supports i18n with next-intl, transactional emails via
57
+ Resend, payments via Stripe, and uses Drizzle ORM with PostgreSQL. Every feature is tested with Vitest
58
+ using a role-based strategy (PUBLIC/USER/ADMIN).
@@ -1,11 +1,19 @@
1
1
  ---
2
2
  name: api-design
3
- description: "REST API design principles, error handling, validation, and security patterns. Use when building API routes, server actions, or backend services."
4
- allowed-tools: "Read, Write, Edit, Glob, Grep"
3
+ description: "REST API design with validation, error handling, auth wrappers, and facades. Use when building API routes, server actions, implementing auth middleware, or designing backend services."
5
4
  ---
6
5
 
7
6
  # API Design Principles
8
7
 
8
+ ## Critical Rules
9
+
10
+ - **Validate all incoming data** with Zod schemas at the API boundary.
11
+ - **Never expose stack traces** or internal details in production error responses.
12
+ - **Always use facades** between presentation and services.
13
+ - **Auth wrappers on every protected endpoint** — `withAuth()`, `withAdmin()`.
14
+ - **Consistent response shapes** — `{ data }` for success, `{ error, code }` for errors.
15
+ - **Parameterized queries only** — never string concatenation for SQL.
16
+
9
17
  ## Route Structure
10
18
 
11
19
  - Use resource-based URLs: `/api/users`, `/api/posts/:id/comments`.
@@ -82,6 +90,39 @@ allowed-tools: "Read, Write, Edit, Glob, Grep"
82
90
  - Check permissions at the resource level: "Can this user access THIS specific post?"
83
91
  - Return `401` for missing/invalid auth, `403` for insufficient permissions.
84
92
 
93
+ ### Auth Wrappers
94
+
95
+ Use auth wrapper functions for consistent protection:
96
+
97
+ ```ts
98
+ // Require any authenticated user
99
+ export async function withAuth() {
100
+ const user = await getCurrentUser();
101
+ if (!user) throw new ApiError(401, "Unauthorized");
102
+ return user;
103
+ }
104
+
105
+ // Require authenticated user with valid token
106
+ export async function withAuthToken(request: Request) {
107
+ const token = request.headers.get("authorization")?.replace("Bearer ", "");
108
+ if (!token) throw new ApiError(401, "Missing token");
109
+ return verifyToken(token);
110
+ }
111
+
112
+ // Dynamic auth — optional session, different behavior for authed/unauthed
113
+ export async function withDynamicAuth() {
114
+ const user = await getCurrentUser();
115
+ return { user, isAuthenticated: !!user };
116
+ }
117
+ ```
118
+
119
+ ## Facades
120
+
121
+ - **Always use facades** between presentation and services.
122
+ - One facade per domain entity in `src/facades/`.
123
+ - Facades handle auth context extraction and coordinate service calls.
124
+ - Routes/pages call facades — never services directly.
125
+
85
126
  ## Rate Limiting
86
127
 
87
128
  - Implement rate limiting on public endpoints and auth endpoints.
@@ -0,0 +1,179 @@
1
+ ---
2
+ name: auth-rbac
3
+ description: "CASL-based authorization with role hierarchies, organization roles, and safe route protection. Use when implementing access control, role-based permissions, or protecting routes and API endpoints."
4
+ ---
5
+
6
+ # Auth & RBAC Patterns
7
+
8
+ ## Critical Rules
9
+
10
+ - **Authorization in services, not routes** — use CASL in the service layer.
11
+ - **Route groups for access control** — `(public)`, `(auth)`, `(app)`, `admin`.
12
+ - **Middleware for redirects** — protect routes at the edge.
13
+ - **Auth wrappers for pages** — `withAuth()`, `withAdmin()` in server components.
14
+ - **Never trust client-side role checks** — always verify server-side.
15
+ - **Principle of least privilege** — grant minimum required permissions.
16
+
17
+ ## Role System
18
+
19
+ ### Application Roles
20
+
21
+ ```ts
22
+ // src/lib/roles.ts
23
+ export const APP_ROLES = ["USER", "ADMIN", "SUPER_ADMIN"] as const;
24
+ export type AppRole = (typeof APP_ROLES)[number];
25
+ ```
26
+
27
+ ### Organization Roles
28
+
29
+ ```ts
30
+ export const ORG_ROLES = ["MEMBER", "MANAGER", "OWNER"] as const;
31
+ export type OrgRole = (typeof ORG_ROLES)[number];
32
+ ```
33
+
34
+ - Every user has an **app role** (global) and an **org role** (per organization).
35
+ - Role checks always consider both: app role for platform features, org role for org resources.
36
+
37
+ ## CASL Authorization
38
+
39
+ ### Ability Definition
40
+
41
+ ```ts
42
+ // src/lib/casl.ts
43
+ import { AbilityBuilder, createMongoAbility, type MongoAbility } from "@casl/ability";
44
+
45
+ type Actions = "create" | "read" | "update" | "delete" | "manage";
46
+ type Subjects = "User" | "Post" | "Organization" | "all";
47
+ export type AppAbility = MongoAbility<[Actions, Subjects]>;
48
+
49
+ export function defineAbilityFor(user: AuthUser): AppAbility {
50
+ const { can, cannot, build } = new AbilityBuilder<AppAbility>(createMongoAbility);
51
+
52
+ // Base permissions for all authenticated users
53
+ can("read", "Post", { published: true });
54
+ can("update", "User", { id: user.id }); // own profile
55
+
56
+ if (user.role === "ADMIN") {
57
+ can("manage", "User");
58
+ can("manage", "Post");
59
+ can("read", "Organization");
60
+ }
61
+
62
+ if (user.role === "SUPER_ADMIN") {
63
+ can("manage", "all");
64
+ }
65
+
66
+ return build();
67
+ }
68
+ ```
69
+
70
+ ### Organization Ability
71
+
72
+ ```ts
73
+ export function defineOrgAbilityFor(user: AuthUser, orgRole: OrgRole): AppAbility {
74
+ const { can, build } = new AbilityBuilder<AppAbility>(createMongoAbility);
75
+
76
+ can("read", "Organization");
77
+
78
+ if (orgRole === "MANAGER" || orgRole === "OWNER") {
79
+ can("update", "Organization");
80
+ can("manage", "User"); // manage org members
81
+ }
82
+
83
+ if (orgRole === "OWNER") {
84
+ can("delete", "Organization");
85
+ }
86
+
87
+ return build();
88
+ }
89
+ ```
90
+
91
+ ## Service Layer Authorization
92
+
93
+ Check permissions in the **service layer**, never in presentation or DAL:
94
+
95
+ ```ts
96
+ // src/services/post.service.ts
97
+ import { ForbiddenError } from "@casl/ability";
98
+ import { defineAbilityFor } from "@/lib/casl";
99
+
100
+ export async function deletePost(user: AuthUser, postId: string) {
101
+ const ability = defineAbilityFor(user);
102
+ const post = await findPostById(postId);
103
+
104
+ ForbiddenError.from(ability).throwUnlessCan("delete", {
105
+ ...post,
106
+ __typename: "Post",
107
+ });
108
+
109
+ return removePost(postId);
110
+ }
111
+ ```
112
+
113
+ ## Safe Route Protection
114
+
115
+ ### Middleware-Level
116
+
117
+ ```ts
118
+ // middleware.ts
119
+ const publicRoutes = ["/", "/login", "/register", "/api/webhook"];
120
+ const adminRoutes = ["/admin"];
121
+
122
+ export async function middleware(request: NextRequest) {
123
+ const session = await getSession();
124
+
125
+ if (!session && !publicRoutes.some(r => request.nextUrl.pathname.startsWith(r))) {
126
+ return NextResponse.redirect(new URL("/login", request.url));
127
+ }
128
+
129
+ if (adminRoutes.some(r => request.nextUrl.pathname.startsWith(r))) {
130
+ if (session?.user.role !== "ADMIN" && session?.user.role !== "SUPER_ADMIN") {
131
+ return NextResponse.redirect(new URL("/", request.url));
132
+ }
133
+ }
134
+ }
135
+ ```
136
+
137
+ ### Route Group Structure
138
+
139
+ ```
140
+ src/app/
141
+ (public)/ # No auth required — landing, login, register
142
+ login/
143
+ register/
144
+ (auth)/ # Auth required, any role — onboarding
145
+ onboarding/
146
+ (app)/ # Auth required, active user — main app
147
+ dashboard/
148
+ settings/
149
+ admin/ # Admin only — user management, app settings
150
+ users/
151
+ settings/
152
+ ```
153
+
154
+ ### Auth Wrappers
155
+
156
+ ```ts
157
+ // src/lib/auth-wrappers.ts
158
+ import { getCurrentUser } from "@/lib/auth";
159
+ import { redirect } from "next/navigation";
160
+
161
+ export async function withAuth() {
162
+ const user = await getCurrentUser();
163
+ if (!user) redirect("/login");
164
+ return user;
165
+ }
166
+
167
+ export async function withAdmin() {
168
+ const user = await withAuth();
169
+ if (user.role !== "ADMIN" && user.role !== "SUPER_ADMIN") redirect("/");
170
+ return user;
171
+ }
172
+
173
+ export async function withOrgRole(orgId: string, requiredRole: OrgRole) {
174
+ const user = await withAuth();
175
+ const membership = await getOrgMembership(user.id, orgId);
176
+ if (!membership || !hasOrgRole(membership.role, requiredRole)) redirect("/");
177
+ return { user, membership };
178
+ }
179
+ ```
@@ -0,0 +1,212 @@
1
+ ---
2
+ name: better-auth-patterns
3
+ description: "Better Auth setup with session management, social login, organization plugin, and middleware. Use when implementing authentication, adding social login providers, or managing user sessions with Better Auth."
4
+ ---
5
+
6
+ # Better Auth Patterns
7
+
8
+ ## Critical Rules
9
+
10
+ - **Server-side session check** — use `getCurrentUser()` in RSC and Server Actions.
11
+ - **Client-side `useSession()`** — only in Client Components for UI state.
12
+ - **Middleware for redirects** — protect routes at the edge, not in pages.
13
+ - **Never expose auth secrets** — keep `BETTER_AUTH_SECRET` server-only.
14
+ - **Use plugins** — `organization()`, `admin()` for built-in features.
15
+ - **Social login always available** — Google + GitHub as defaults.
16
+
17
+ ## Server Setup
18
+
19
+ ```ts
20
+ // src/lib/auth.ts
21
+ import { betterAuth } from "better-auth";
22
+ import { drizzleAdapter } from "better-auth/adapters/drizzle";
23
+ import { organization, admin } from "better-auth/plugins";
24
+ import { db } from "@/lib/db";
25
+
26
+ export const auth = betterAuth({
27
+ database: drizzleAdapter(db, { provider: "pg" }),
28
+ emailAndPassword: { enabled: true },
29
+ socialProviders: {
30
+ google: {
31
+ clientId: process.env.GOOGLE_CLIENT_ID!,
32
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
33
+ },
34
+ github: {
35
+ clientId: process.env.GITHUB_CLIENT_ID!,
36
+ clientSecret: process.env.GITHUB_CLIENT_SECRET!,
37
+ },
38
+ },
39
+ plugins: [
40
+ organization(),
41
+ admin(),
42
+ ],
43
+ session: {
44
+ expiresIn: 60 * 60 * 24 * 7, // 7 days
45
+ updateAge: 60 * 60 * 24, // refresh daily
46
+ },
47
+ });
48
+ ```
49
+
50
+ ## Client Setup
51
+
52
+ ```ts
53
+ // src/lib/auth-client.ts
54
+ import { createAuthClient } from "better-auth/react";
55
+ import { organizationClient, adminClient } from "better-auth/client/plugins";
56
+
57
+ export const authClient = createAuthClient({
58
+ plugins: [organizationClient(), adminClient()],
59
+ });
60
+
61
+ export const { useSession, signIn, signUp, signOut } = authClient;
62
+ ```
63
+
64
+ ## API Route Handler
65
+
66
+ ```ts
67
+ // src/app/api/auth/[...all]/route.ts
68
+ import { auth } from "@/lib/auth";
69
+ import { toNextJsHandler } from "better-auth/next-js";
70
+
71
+ export const { GET, POST } = toNextJsHandler(auth);
72
+ ```
73
+
74
+ ## Session Management
75
+
76
+ ### Server-Side Session
77
+
78
+ ```ts
79
+ // src/lib/auth-server.ts
80
+ import { auth } from "@/lib/auth";
81
+ import { headers } from "next/headers";
82
+
83
+ export async function getCurrentUser() {
84
+ const session = await auth.api.getSession({
85
+ headers: await headers(),
86
+ });
87
+ return session?.user ?? null;
88
+ }
89
+
90
+ export async function requireAuth() {
91
+ const user = await getCurrentUser();
92
+ if (!user) redirect("/login");
93
+ return user;
94
+ }
95
+ ```
96
+
97
+ ### Client-Side Session
98
+
99
+ ```tsx
100
+ "use client";
101
+ import { useSession } from "@/lib/auth-client";
102
+
103
+ export function UserMenu() {
104
+ const { data: session, isPending } = useSession();
105
+
106
+ if (isPending) return <Skeleton />;
107
+ if (!session) return <LoginButton />;
108
+
109
+ return <span>{session.user.name}</span>;
110
+ }
111
+ ```
112
+
113
+ ## Authentication Flows
114
+
115
+ ### Sign Up
116
+
117
+ ```tsx
118
+ "use client";
119
+ import { authClient } from "@/lib/auth-client";
120
+
121
+ async function handleSignUp(data: SignUpInput) {
122
+ const { error } = await authClient.signUp.email({
123
+ email: data.email,
124
+ password: data.password,
125
+ name: data.name,
126
+ });
127
+ if (error) toast.error(error.message);
128
+ else router.push("/dashboard");
129
+ }
130
+ ```
131
+
132
+ ### Social Login
133
+
134
+ ```tsx
135
+ async function handleGoogleLogin() {
136
+ await authClient.signIn.social({ provider: "google" });
137
+ }
138
+ ```
139
+
140
+ ### Sign Out
141
+
142
+ ```tsx
143
+ async function handleSignOut() {
144
+ await authClient.signOut();
145
+ router.push("/");
146
+ }
147
+ ```
148
+
149
+ ## Middleware
150
+
151
+ ```ts
152
+ // middleware.ts
153
+ import { betterFetch } from "@better-fetch/fetch";
154
+ import { NextResponse } from "next/server";
155
+ import type { NextRequest } from "next/server";
156
+ import type { Session } from "better-auth/types";
157
+
158
+ const publicRoutes = ["/", "/login", "/register", "/api/auth"];
159
+
160
+ export async function middleware(request: NextRequest) {
161
+ const { pathname } = request.nextUrl;
162
+
163
+ // Skip public routes
164
+ if (publicRoutes.some((r) => pathname.startsWith(r))) {
165
+ return NextResponse.next();
166
+ }
167
+
168
+ // Check session
169
+ const { data: session } = await betterFetch<Session>(
170
+ "/api/auth/get-session",
171
+ {
172
+ baseURL: request.nextUrl.origin,
173
+ headers: { cookie: request.headers.get("cookie") ?? "" },
174
+ }
175
+ );
176
+
177
+ if (!session) {
178
+ return NextResponse.redirect(new URL("/login", request.url));
179
+ }
180
+
181
+ // Admin route protection
182
+ if (pathname.startsWith("/admin") && session.user.role !== "admin") {
183
+ return NextResponse.redirect(new URL("/", request.url));
184
+ }
185
+
186
+ return NextResponse.next();
187
+ }
188
+
189
+ export const config = {
190
+ matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
191
+ };
192
+ ```
193
+
194
+ ## Organization Plugin
195
+
196
+ ```tsx
197
+ // Create organization
198
+ const { data: org } = await authClient.organization.create({
199
+ name: "Acme Inc",
200
+ slug: "acme",
201
+ });
202
+
203
+ // Invite member
204
+ await authClient.organization.inviteMember({
205
+ email: "user@example.com",
206
+ role: "member",
207
+ organizationId: org.id,
208
+ });
209
+
210
+ // Switch active organization
211
+ await authClient.organization.setActive({ organizationId: org.id });
212
+ ```