Packages
@react-native-vibe-code/auth
Authentication utilities with Better Auth and Google OAuth
Overview
This package provides authentication abstraction for React Native Vibe Code:
- Better Auth Integration: Session management and OAuth
- Google OAuth: Social login support
- Team Management: User team retrieval
- Client/Server Split: Separate exports for each environment
- Polar Integration: Subscription management hooks
Installation
pnpm add @react-native-vibe-code/authConfiguration
Environment Variables
# Auth secret (min 32 chars)
BETTER_AUTH_SECRET=your_secret_key
# Google OAuth
GOOGLE_CLIENT_ID=your_client_id
GOOGLE_CLIENT_SECRET=your_client_secret
# App URLs
NEXT_PUBLIC_PROD_URL=https://your-domain.com
NEXT_PUBLIC_APP_URL=http://localhost:3210Usage
Client-Side
'use client'
import { useSession, signInWithGoogle, signOut } from '@react-native-vibe-code/auth/client'
function AuthButton() {
const { data: session, isPending: loading } = useSession()
if (loading) {
return <div>Loading...</div>
}
if (session?.user) {
return (
<div>
<span>Welcome, {session.user.email}</span>
<button onClick={() => signOut()}>Sign Out</button>
</div>
)
}
return (
<button onClick={() => signInWithGoogle()}>
Sign In with Google
</button>
)
}Server-Side
import { getUserTeam, getAuthHeaders } from '@react-native-vibe-code/auth'
// Get user's team
const team = await getUserTeam(userId)
if (team) {
console.log(`Team: ${team.name}`)
console.log(`Tier: ${team.tier}`)
}
// Get auth headers
const headers = await getAuthHeaders()Exports
Client Exports (@react-native-vibe-code/auth/client)
// Auth client instance
export { authClient }
// Sign in with Google
export function signInWithGoogle(callbackURL?: string): Promise<void>
// Sign out (redirects to home)
export function signOut(): Promise<void>
// Session hook
export { useSession } from 'better-auth/react'Server Exports (@react-native-vibe-code/auth)
// Get user team from database
export function getUserTeam(userId: string): Promise<UserTeam | null>
// Get auth headers
export function getAuthHeaders(): Promise<Headers>
// Types
export type { UserTeam }Types
interface UserTeam {
id: string
name: string
email: string
tier: string
}
interface Session {
user: {
id: string
email: string
name: string
image: string
}
session: {
id: string
expiresAt: Date
token: string
}
}Client Configuration
The auth client automatically detects the base URL:
// Browser environment
window.location.origin
// SSR/Development
'http://localhost:3210'
// Production (from env)
process.env.NEXT_PUBLIC_PROD_URLError Handling
Built-in error handling for common scenarios:
const authClient = createAuthClient({
// ...
onError: (ctx) => {
if (ctx.error.status === 429) {
// Handle rate limiting
console.log('Too many requests')
}
}
})Better Auth Configuration
When setting up Better Auth in your app:
// lib/auth/config.ts
import { betterAuth } from 'better-auth'
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
import { polar } from '@polar-sh/better-auth'
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: 'pg',
schema: { user, session, account, verification }
}),
session: {
expiresIn: 60 * 60 * 24 * 7, // 7 days
updateAge: 60 * 60 * 24 // 1 day
},
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}
},
plugins: [
polar({
accessToken: process.env.POLAR_ACCESS_TOKEN,
server: process.env.POLAR_SERVER
})
],
trustedOrigins: [
'http://localhost:3210',
'https://your-domain.com',
// Add preview URLs
]
})Integration Patterns
With Next.js App Router
// app/api/auth/[...all]/route.ts
import { auth } from '@/lib/auth/config'
import { toNextJsHandler } from 'better-auth/next-js'
export const { GET, POST } = toNextJsHandler(auth)Protected Routes
// Server component
import { getServerSession } from '@/lib/auth'
async function ProtectedPage() {
const session = await getServerSession()
if (!session) {
redirect('/login')
}
return <div>Protected content</div>
}API Routes
import { getServerSession } from '@/lib/auth'
export async function GET() {
const session = await getServerSession()
if (!session) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
// Handle authenticated request
}Package Structure
packages/auth/
├── src/
│ ├── index.ts # Main exports (server + re-exports)
│ ├── client.ts # Client-side utilities
│ └── server.ts # Server-side utilities
├── package.json
└── tsconfig.jsonDependencies
better-auth- Authentication framework@polar-sh/better-auth- Polar integration@polar-sh/sdk- Polar SDK@react-native-vibe-code/database- Database access@react-native-vibe-code/config- Configuration