Developer guidance for Claude Code when working with this SvelteKit template.
# Development
bun run dev # Start dev server
bun run build # Build for production
bun run check # Type checking
bun run lint && bun run format # Code quality
# Database
bun run local:db:up # Start PostgreSQL container
bun run local:db:down # Stop PostgreSQL container
bun run test:server # Run database tests
# Scaffolding
bun run create:page <path> # New page template
bun run create:md <filename> # Markdown files for all locales
bun run create:api-controller <path> # API endpoint template- SvelteKit v5 + TypeScript + Vite
- shadcn-svelte (bits-ui) + Tailwind CSS v4
- Drizzle ORM + PostgreSQL + Docker
- better-auth - Modern authentication library with OAuth & email/password
- sveltekit-i18n (Polish/English with RTL/LTR)
- Vitest + Playwright for testing
- Authentication System - better-auth with OAuth (Google) & email/password
- Database Layer - Abstract service pattern with CRUD operations
- Internationalization - Polish & English with RTL/LTR support
- Theme System - Dark/light mode with persistence
- Cookie Management - GDPR-compliant consent system
- SEO Optimized - Meta tags, structured data, sitemap
src/lib/
├── server/
│ ├── database/ # Database services & tests
│ └── auth/ # better-auth configuration & handlers
├── client/
│ ├── auth/ # Client-side auth utilities
│ └── configurations/ # Client configs (routes, themes)
├── components/
│ ├── ui/ # shadcn-svelte components
│ ├── signin/ # Authentication components
│ └── signup/ # Registration components
├── api/configurations/ # Server configs
├── i18n/ # Translations (en-US, pl-PL)
└── resources/markdown/ # Localized content
src/routes/
├── [[lang]]/ # Internationalized routes
│ ├── (application)/ # App pages with auth routes
│ │ └── (auth)/ # Authentication pages (signin/signup)
│ └── (site)/ # Content pages (policies)
├── api/ # Server endpoints
└── auth/ # better-auth API endpoints
The template uses better-auth, a modern authentication library designed for TypeScript applications with excellent SvelteKit integration.
- Email & Password Authentication - Traditional signup/signin flow with email verification
- OAuth Providers - Google OAuth integration (configurable for additional providers)
- Session Management - Secure session handling with database persistence
- Route Protection - Automatic authentication middleware for protected routes
- TypeScript Support - Full type safety for user sessions and authentication state
import { betterAuth } from 'better-auth';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: 'pg',
schema: { user, session, account, verification }
}),
emailAndPassword: {
enabled: true
},
socialProviders: {
google: {
clientId: env.GOOGLE_CLIENT_ID,
clientSecret: env.GOOGLE_CLIENT_SECRET
}
},
plugins: [sveltekitCookies(getRequestEvent)]
});import { createAuthClient } from 'better-auth/svelte';
const client = createAuthClient();
export default client;The authentication system uses four main tables:
- user - User profiles with email, name, and verification status
- session - Active user sessions with expiration and metadata
- account - OAuth provider accounts linked to users
- verification - Email verification tokens and codes
import authClient from '$lib/client/auth/client';
// Get current session (reactive)
const session = authClient.useSession();
// Sign in with email/password
await authClient.signIn.email({
email: 'user@example.com',
password: 'password'
});
// Sign in with Google OAuth
await authClient.signIn.social({
provider: 'google',
callbackURL: '/dashboard'
});
// Sign up new user
await authClient.signUp.email({
email: 'user@example.com',
password: 'password',
name: 'User Name'
});
// Sign out
await authClient.signOut();// In +layout.server.ts or +page.server.ts
export async function load({ event }) {
const session = event.locals.session;
const user = event.locals.user;
return {
user: user ? { name: user.name, email: user.email } : null
};
}Routes are automatically protected based on configuration in src/lib/client/configurations/routes.ts. Set authenticationRequired: false to make routes publicly accessible.
// Protected route (default)
{ path: '/dashboard', authenticationRequired: true }
// Public route
{ path: '/about', authenticationRequired: false }Required environment variables for authentication:
# For OAuth providers
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
# Database connection (already configured)
DATABASE_URL=postgresql://...src/lib/components/signin/signin.svelte- Complete signin form with OAuth and email/password optionssrc/lib/components/signup/signup.svelte- User registration formsrc/lib/components/signin/providers/- Individual provider components (Google, email/password)
When migrating from other authentication libraries:
- Update imports from
better-auth/svelte - Replace auth calls with better-auth equivalents
- Update session access patterns in server code
- Migrate database schema using provided auth tables
Use $lib/server/database/services/users.ts and src/routes/api/demo/users/+server.ts for best practices.
import { serviceFactory } from '$lib/server/database/services/provider';
// Get service instance
const userService = serviceFactory.getService(users);
// CRUD operations
const user = await userService.create({ name: 'John', email: 'john@example.com' });
const allUsers = await userService.findAll({ limit: 20 });
const user = await userService.findById(1);
await userService.updateById(1, { name: 'Jane' });
await userService.deleteById(1);
// Advanced queries
const activeUsers = await userService.find((table) => eq(table.status, 'active'), {
limit: 10,
orderBy: desc(table.createdAt)
});// Parse URL params into query conditions
const filters = getUrlFiltersUtil(url, {
searchColumns: [users.name, users.email]
});
// Parse pagination from URL: ?limit=20&offset=40&orderBy=name,-createdAt
const options = getUrlOptionsUtil(url, users);
// Parse body filters
const bodyFilters = getBodyFiltersUtil({ ids: [1, 2, 3] }, { ids: users.id });Client-side API request utilities:
import { GET, POST, PUT, DELETE } from '$lib/api/helpers/request';
// GET with query params
const users = await GET<User[]>('/api/users', {
limit: 20,
searchTerm: 'john',
orderBy: 'name,-createdAt'
});
// POST to create
const user = await POST<CreateData, User>('/api/users', data);
// PUT to update with filters
const updated = await PUT<Data, Filters, User>('/api/users', data, filters);
// DELETE with filters
await DELETE<Filters, void>('/api/users', { ids: [1, 2, 3] });
// SSR with custom fetch
const serverData = await GET('/api/users', { fetch: event.fetch });// In templates
$t('common.navigation.home');
// In TypeScript
t.get('common.navigation.home');
// Translation files: src/lib/i18n/[locale]/[namespace].json
// Supported: en-US, pl-PL (with RTL/LTR support)components/[name]/
├── [name].svelte
└── configurations/ (optional)
└── [config].ts
components/ui/[name]/ # shadcn-svelte
├── [name].svelte
├── index.ts
└── [additional-parts].svelte
# Create dynamic product page
bun run create:page /products/[product_id]
# Create localized content
bun run create:md about-us.md
# Create nested API controller
bun run create:api-controller users/[user_id]/orders- Template repository - customize for your specific needs
- Polish (RTL) and English (LTR) preconfigured
- Policy pages are placeholder content
- Services are cached per table in singleton factory
- Use configuration-driven architecture for maintainable code