← スキル一覧に戻る

auth
by oakoss
Open-source SaaS starter kit with React, TanStack, and Better Auth
⭐ 0🍴 0📅 2026年1月26日
SKILL.md
name: auth description: Better Auth authentication. Use for auth, login, logout, session, user, signup, register, protect, middleware, password, oauth, social
For advanced patterns, OAuth configuration, and session middleware, see reference.md.
Better Auth
Package Structure
packages/auth/
├── src/
│ ├── client.ts # Auth client (React hooks)
│ ├── server.ts # Auth server (Better Auth config)
│ └── index.ts # Public exports
└── package.json
Server Configuration
// packages/auth/src/server.ts
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { betterAuth } from 'better-auth';
import { tanstackStartCookies } from 'better-auth/tanstack-start';
import { db } from '@oakoss/database';
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: 'pg',
usePlural: true, // Uses 'users', 'sessions', etc.
}),
emailAndPassword: { enabled: true },
plugins: [tanstackStartCookies()], // Must be last plugin in array
});
Client Configuration
// packages/auth/src/client.ts
import { createAuthClient } from 'better-auth/client';
import { inferAdditionalFields } from 'better-auth/client/plugins';
import { type auth } from '@oakoss/auth/server';
export const authClient = createAuthClient({
baseURL: process.env.PUBLIC_APP_URL ?? 'http://localhost:3000',
plugins: [inferAdditionalFields<typeof auth>()],
});
API Route Handler
// apps/web/src/routes/api/auth/$.ts
import { createFileRoute } from '@tanstack/react-router';
import { auth } from '@oakoss/auth/server';
export const Route = createFileRoute('/api/auth/$')({
server: {
handlers: {
GET: ({ request }) => auth.handler(request),
POST: ({ request }) => auth.handler(request),
},
},
});
Sign In/Sign Up
import { authClient } from '@oakoss/auth/client';
// Sign up with email
await authClient.signUp.email({
name: 'John Doe',
email: 'john@example.com',
password: 'password123',
});
// Sign in with email
await authClient.signIn.email({
email: 'john@example.com',
password: 'password123',
callbackURL: '/dashboard',
});
// Sign in with social provider
await authClient.signIn.social({
provider: 'github',
callbackURL: '/dashboard',
});
Session Management
// Reactive hook
function UserProfile() {
const { data: session, isPending } = authClient.useSession();
if (isPending) return <Spinner />;
if (!session) return <LoginPrompt />;
return <div>Welcome, {session.user.name}</div>;
}
// One-time fetch
const { data: session } = await authClient.getSession();
Route Protection (beforeLoad)
// apps/web/src/routes/_app/route.tsx
import { createFileRoute, redirect } from '@tanstack/react-router';
import { auth } from '@oakoss/auth/server';
export const Route = createFileRoute('/_app')({
beforeLoad: async ({ context }) => {
const session = await auth.api.getSession({
headers: context.request.headers,
});
if (!session) {
throw redirect({ to: '/login' });
}
return { user: session.user };
},
component: AppLayout,
});
Server Function Auth Check
import { createServerFn } from '@tanstack/react-start';
import { auth } from '@oakoss/auth/server';
const deletePost = createServerFn({ method: 'POST' })
.inputValidator(z.object({ id: z.string() }))
.handler(async ({ data, request }) => {
const session = await auth.api.getSession({ headers: request.headers });
if (!session) {
return { error: 'Unauthorized', code: 'AUTH_REQUIRED' };
}
// Check ownership
const post = await db.query.posts.findFirst({
where: eq(posts.id, data.id),
});
if (post?.authorId !== session.user.id) {
return { error: 'Not authorized', code: 'FORBIDDEN' };
}
await db.delete(posts).where(eq(posts.id, data.id));
return { success: true };
});
Sign Out
await authClient.signOut({
fetchOptions: {
onSuccess: () => (window.location.href = '/login'),
},
});
Common Mistakes
| Mistake | Correct Pattern |
|---|---|
| Client-side auth checks only | Validate session server-side in beforeLoad |
| Missing request headers | Pass { headers: request.headers } to API |
| Not handling loading states | Check isPending before rendering |
| Hardcoding callback URLs | Use environment variables |
| Storing session in useState | Use authClient.useSession() hook |
| Missing auth handler route | Create /api/auth/$.ts catch-all route |
Not using usePlural in adapter | Set usePlural: true for Better Auth |
| Importing server code in client | Use @oakoss/auth/server only server-side |
Delegation
- Route protection: For beforeLoad patterns, see tanstack-router skill
- Server functions: For auth in server functions, see tanstack-start skill
- Database: For user queries, see database skill
- Code review: After implementing auth, delegate to
code-revieweragent
Topic References
- Auth Reference - Social providers, plugins, session types, error handling
スコア
総合スコア
65/100
リポジトリの品質指標に基づく評価
✓SKILL.md
SKILL.mdファイルが含まれている
+20
✓LICENSE
ライセンスが設定されている
+10
○説明文
100文字以上の説明がある
0/10
○人気
GitHub Stars 100以上
0/15
✓最近の活動
3ヶ月以内に更新
+5
○フォーク
10回以上フォークされている
0/5
✓Issue管理
オープンIssueが50未満
+5
✓言語
プログラミング言語が設定されている
+5
✓タグ
1つ以上のタグが設定されている
+5
レビュー
💬
レビュー機能は近日公開予定です

