Self-hosted TypeScript auth for Cloudflare Workers with OAuth, 2FA, passkeys, organizations, and 80+ production-ready endpoints.
›Requires Drizzle ORM or Kysely for D1 (no direct adapter); use drizzleAdapter() or new Kysely({ dialect: new D1Dialect() }) with nodejs_compat flag in wrangler.toml
›Provides 80+ auto-generated REST endpoints covering authentication, sessions, 2FA, organizations, admin operations, and social OAuth—zero endpoint code needed
import{ betterAuth }from"better-auth";import{ Kysely, CamelCasePlugin }from"kysely";import{ D1Dialect }from"kysely-d1";typeEnv={DB: D1Database;BETTER_AUTH_SECRET:string;// ... other env vars};exportfunctioncreateAuth(env: Env){returnbetterAuth({ secret: env.BETTER_AUTH_SECRET,// Kysely with D1Dialect database:{ db:newKysely({ dialect:newD1Dialect({ database: env.DB,}), plugins:[// CRITICAL: Required if using Drizzle schema with snake_casenewCamelCasePlugin(),],}), type:"sqlite",}, emailAndPassword:{ enabled:true,},// ... other config});}
Why CamelCasePlugin?
If your Drizzle schema uses snake_case column names (e.g., email_verified), but better-auth expects camelCase (e.g., emailVerified), the CamelCasePlugin automatically converts between the two.
⚠️ Cloudflare Workers Note: D1 database bindings are only available inside the request handler (the fetch() function). You cannot initialize better-auth outside the request context. Use a factory function pattern:
// ❌ WRONG - DB binding not available outside requestconst db =drizzle(env.DB,{ schema })// env.DB doesn't exist hereexportconst auth =betterAuth({ database:drizzleAdapter(db,{ provider:"sqlite"})})// ✅ CORRECT - Create auth instance per-requestexportdefault{fetch(request, env, ctx){const db =drizzle(env.DB,{ schema })const auth =betterAuth({ database:drizzleAdapter(db,{ provider:"sqlite"})})return auth.handler(request)}}
Community Validation: Multiple production implementations confirm this pattern (Medium, AnswerOverflow, official Hono examples).
Framework Integrations
TanStack Start
⚠️ CRITICAL: TanStack Start requires the reactStartCookies plugin to handle cookie setting properly.
import{ betterAuth }from"better-auth";import{ drizzleAdapter }from"better-auth/adapters/drizzle";import{ reactStartCookies }from"better-auth/react-start";exportconst auth =betterAuth({ database:drizzleAdapter(db,{ provider:"sqlite"}), plugins:[twoFactor(),organization(),reactStartCookies(),// ⚠️ MUST be LAST plugin],});
Why it's needed: TanStack Start uses a special cookie handling system. Without this plugin, auth functions like signInEmail() and signUpEmail() won't set cookies properly, causing authentication to fail.
Important: The reactStartCookies plugin must be the last plugin in the array.
Session Nullability Pattern: When using useSession() in TanStack Start, the session object always exists, but session.user and session.session are null when not logged in:
const{ data: session }= authClient.useSession()// When NOT logged in:console.log(session)// { user: null, session: null }console.log(!!session)// true (unexpected!)// Correct check:if(session?.user){// User is logged in}
Always check session?.user or session?.session, not just session. This is expected behavior (session object container always exists).
The skills CLI fetches better-auth from GitHub repository jezweb/claude-skills and configures it for Cursor.
3
Select Cursor when prompted
The CLI will show a list of available agents. Use arrow keys to navigate and space to select Cursor:
◆ Which agents do you want to install to?
│
│ ── Universal (.agents/skills) ── always included ────
│ • Amp
│ • Antigravity
│ • Cline
│ • Codex
│ ●Cursor(selected)
│ • Cursor
│ • Windsurf
4
Verify installation
Confirm successful installation by checking the skill directory location:
.cursor/skills/better-auth
Reload or restart Cursor to activate better-auth. Access the skill through slash commands (e.g., /better-auth) or your agent's skill management interface.
⚠
Security & Verification Notice
We perform automated surface-level scans (Gen AI Scanner, Socket, Snyk) during installation. These checks detect common vulnerabilities but do not guarantee complete security. Always review skill source code and verify the publisher's reputation before production use.
Skills execute code in your development environment. Always verify the publisher's identity, review recent commits, and test in isolated environments before production deployment.
›Access to product documentation and roadmap tools (Jira, Notion, etc.)
›Understanding of product management frameworks (RICE, Jobs-to-be-Done, etc.)
›Stakeholder contact information and communication channels
Time Estimate
30-60 minutes to see productivity improvements
Installation Steps
1.Install product management skill
2.Start with user story generation for known feature
3.Progress to competitive analysis: research 2-3 competitors
4.Use for roadmap prioritization: apply RICE/ICE scoring
5.Draft stakeholder communications and refine based on feedback
6.Build template library for recurring PM tasks
7.Share effective prompts with product team
Common Pitfalls
⚠Not validating competitive research—verify facts before sharing
⚠Accepting user stories without involving engineering team
⚠Over-relying on frameworks without qualitative judgment
⚠Not customizing outputs to company culture and communication style
⚠Skipping stakeholder validation of generated requirements
Best Practices▌
✓ Do
+Validate research and competitive analysis with real data
+Collaborate with engineering when generating technical requirements
+Customize frameworks and templates to your company context
+Use skill for first drafts, refine with stakeholder input
+Document successful prompt patterns for PM tasks
+Combine AI efficiency with human judgment and intuition
✗ Don't
−Don't publish competitive analysis without fact-checking
−Don't finalize user stories without engineering review
−Don't make prioritization decisions solely on AI scoring
−Don't skip customer validation of generated requirements
−Don't ignore company-specific context and culture
💡 Pro Tips
★Provide context: company goals, constraints, customer feedback
★Ask for alternatives: 'Show 3 ways to prioritize this roadmap'
★Request stakeholder-specific formatting: 'Executive summary vs. engineering spec'
★Use skill for 70% generation + 30% customization to company needs
When to Use This▌
✓ Use When
Use for user story writing, competitive research, roadmap prioritization, stakeholder communication, and PRD drafting. Best for reducing repetitive documentation and research work.
✗ Avoid When
Avoid for strategic product vision (requires deep customer empathy), pricing decisions (needs market and financial expertise), or when face-to-face customer discovery is more valuable than speed.
Learning Path▌
1Basic: user stories, feature specs, status updates