Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
214 lines
6.4 KiB
Markdown
214 lines
6.4 KiB
Markdown
---
|
|
name: create-auth-skill
|
|
description: Skill for creating auth layers in TypeScript/JavaScript apps using Better Auth.
|
|
---
|
|
|
|
# Create Auth Skill
|
|
|
|
Guide for adding authentication to TypeScript/JavaScript applications using Better Auth.
|
|
|
|
**For code examples and syntax, see [better-auth.com/docs](https://better-auth.com/docs).**
|
|
|
|
---
|
|
|
|
## Decision Tree
|
|
|
|
```
|
|
Is this a new/empty project?
|
|
├─ YES → New project setup
|
|
│ 1. Identify framework
|
|
│ 2. Choose database
|
|
│ 3. Install better-auth
|
|
│ 4. Create auth.ts + auth-client.ts
|
|
│ 5. Set up route handler
|
|
│ 6. Run CLI migrate/generate
|
|
│ 7. Add features via plugins
|
|
│
|
|
└─ NO → Does project have existing auth?
|
|
├─ YES → Migration/enhancement
|
|
│ • Audit current auth for gaps
|
|
│ • Plan incremental migration
|
|
│ • See migration guides in docs
|
|
│
|
|
└─ NO → Add auth to existing project
|
|
1. Analyze project structure
|
|
2. Install better-auth
|
|
3. Create auth config
|
|
4. Add route handler
|
|
5. Run schema migrations
|
|
6. Integrate into existing pages
|
|
```
|
|
|
|
---
|
|
|
|
## Installation
|
|
|
|
**Core:** `npm install better-auth`
|
|
|
|
**Scoped packages (as needed):**
|
|
| Package | Use case |
|
|
|---------|----------|
|
|
| `@better-auth/passkey` | WebAuthn/Passkey auth |
|
|
| `@better-auth/sso` | SAML/OIDC enterprise SSO |
|
|
| `@better-auth/stripe` | Stripe payments |
|
|
| `@better-auth/scim` | SCIM user provisioning |
|
|
| `@better-auth/expo` | React Native/Expo |
|
|
|
|
---
|
|
|
|
## Environment Variables
|
|
|
|
```env
|
|
BETTER_AUTH_SECRET=<32+ chars, generate with: openssl rand -base64 32>
|
|
BETTER_AUTH_URL=http://localhost:3000
|
|
DATABASE_URL=<your database connection string>
|
|
```
|
|
|
|
Add OAuth secrets as needed: `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`, `GOOGLE_CLIENT_ID`, etc.
|
|
|
|
---
|
|
|
|
## Server Config (auth.ts)
|
|
|
|
**Location:** `lib/auth.ts` or `src/lib/auth.ts`
|
|
|
|
**Minimal config needs:**
|
|
- `database` - Connection or adapter
|
|
- `emailAndPassword: { enabled: true }` - For email/password auth
|
|
|
|
**Standard config adds:**
|
|
- `socialProviders` - OAuth providers (google, github, etc.)
|
|
- `emailVerification.sendVerificationEmail` - Email verification handler
|
|
- `emailAndPassword.sendResetPassword` - Password reset handler
|
|
|
|
**Full config adds:**
|
|
- `plugins` - Array of feature plugins
|
|
- `session` - Expiry, cookie cache settings
|
|
- `account.accountLinking` - Multi-provider linking
|
|
- `rateLimit` - Rate limiting config
|
|
|
|
**Export types:** `export type Session = typeof auth.$Infer.Session`
|
|
|
|
---
|
|
|
|
## Client Config (auth-client.ts)
|
|
|
|
**Import by framework:**
|
|
| Framework | Import |
|
|
|-----------|--------|
|
|
| React/Next.js | `better-auth/react` |
|
|
| Vue | `better-auth/vue` |
|
|
| Svelte | `better-auth/svelte` |
|
|
| Solid | `better-auth/solid` |
|
|
| Vanilla JS | `better-auth/client` |
|
|
|
|
**Client plugins** go in `createAuthClient({ plugins: [...] })`.
|
|
|
|
**Common exports:** `signIn`, `signUp`, `signOut`, `useSession`, `getSession`
|
|
|
|
---
|
|
|
|
## Route Handler Setup
|
|
|
|
| Framework | File | Handler |
|
|
|-----------|------|---------|
|
|
| Next.js App Router | `app/api/auth/[...all]/route.ts` | `toNextJsHandler(auth)` → export `{ GET, POST }` |
|
|
| Next.js Pages | `pages/api/auth/[...all].ts` | `toNextJsHandler(auth)` → default export |
|
|
| Express | Any file | `app.all("/api/auth/*", toNodeHandler(auth))` |
|
|
| SvelteKit | `src/hooks.server.ts` | `svelteKitHandler(auth)` |
|
|
| SolidStart | Route file | `solidStartHandler(auth)` |
|
|
| Hono | Route file | `auth.handler(c.req.raw)` |
|
|
|
|
**Next.js Server Components:** Add `nextCookies()` plugin to auth config.
|
|
|
|
---
|
|
|
|
## Database Migrations
|
|
|
|
| Adapter | Command |
|
|
|---------|---------|
|
|
| Built-in Kysely | `npx @better-auth/cli@latest migrate` (applies directly) |
|
|
| Prisma | `npx @better-auth/cli@latest generate --output prisma/schema.prisma` then `npx prisma migrate dev` |
|
|
| Drizzle | `npx @better-auth/cli@latest generate --output src/db/auth-schema.ts` then `npx drizzle-kit push` |
|
|
|
|
**Re-run after adding plugins.**
|
|
|
|
---
|
|
|
|
## Database Adapters
|
|
|
|
| Database | Setup |
|
|
|----------|-------|
|
|
| SQLite | Pass `better-sqlite3` or `bun:sqlite` instance directly |
|
|
| PostgreSQL | Pass `pg.Pool` instance directly |
|
|
| MySQL | Pass `mysql2` pool directly |
|
|
| Prisma | `prismaAdapter(prisma, { provider: "postgresql" })` from `better-auth/adapters/prisma` |
|
|
| Drizzle | `drizzleAdapter(db, { provider: "pg" })` from `better-auth/adapters/drizzle` |
|
|
| MongoDB | `mongodbAdapter(db)` from `better-auth/adapters/mongodb` |
|
|
|
|
---
|
|
|
|
## Common Plugins
|
|
|
|
| Plugin | Server Import | Client Import | Purpose |
|
|
|--------|---------------|---------------|---------|
|
|
| `twoFactor` | `better-auth/plugins` | `twoFactorClient` | 2FA with TOTP/OTP |
|
|
| `organization` | `better-auth/plugins` | `organizationClient` | Teams/orgs |
|
|
| `admin` | `better-auth/plugins` | `adminClient` | User management |
|
|
| `bearer` | `better-auth/plugins` | - | API token auth |
|
|
| `openAPI` | `better-auth/plugins` | - | API docs |
|
|
| `passkey` | `@better-auth/passkey` | `passkeyClient` | WebAuthn |
|
|
| `sso` | `@better-auth/sso` | - | Enterprise SSO |
|
|
|
|
**Plugin pattern:** Server plugin + client plugin + run migrations.
|
|
|
|
---
|
|
|
|
## Auth UI Implementation
|
|
|
|
**Sign in flow:**
|
|
1. `signIn.email({ email, password })` or `signIn.social({ provider, callbackURL })`
|
|
2. Handle `error` in response
|
|
3. Redirect on success
|
|
|
|
**Session check (client):** `useSession()` hook returns `{ data: session, isPending }`
|
|
|
|
**Session check (server):** `auth.api.getSession({ headers: await headers() })`
|
|
|
|
**Protected routes:** Check session, redirect to `/sign-in` if null.
|
|
|
|
---
|
|
|
|
## Security Checklist
|
|
|
|
- [ ] `BETTER_AUTH_SECRET` set (32+ chars)
|
|
- [ ] `advanced.useSecureCookies: true` in production
|
|
- [ ] `trustedOrigins` configured
|
|
- [ ] Rate limits enabled
|
|
- [ ] Email verification enabled
|
|
- [ ] Password reset implemented
|
|
- [ ] 2FA for sensitive apps
|
|
- [ ] CSRF protection NOT disabled
|
|
- [ ] `account.accountLinking` reviewed
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
| Issue | Fix |
|
|
|-------|-----|
|
|
| "Secret not set" | Add `BETTER_AUTH_SECRET` env var |
|
|
| "Invalid Origin" | Add domain to `trustedOrigins` |
|
|
| Cookies not setting | Check `baseURL` matches domain; enable secure cookies in prod |
|
|
| OAuth callback errors | Verify redirect URIs in provider dashboard |
|
|
| Type errors after adding plugin | Re-run CLI generate/migrate |
|
|
|
|
---
|
|
|
|
## Resources
|
|
|
|
- [Docs](https://better-auth.com/docs)
|
|
- [Examples](https://github.com/better-auth/examples)
|
|
- [Plugins](https://better-auth.com/docs/concepts/plugins)
|
|
- [CLI](https://better-auth.com/docs/concepts/cli)
|
|
- [Migration Guides](https://better-auth.com/docs/guides) |