Core Concepts
Use The Platform
Verge Kit prefers the framework and platform tools already in the project.
Use Astro pages, API routes, Actions, middleware, and config before adding a new local abstraction. Add helpers only when they remove repeated code or protect a real boundary.
D1 First
D1 is the supported runtime database.
Use the local src/db modules from app code. Do not import drizzle-orm/d1
directly in routes, pages, actions, or components.
This keeps future Hyperdrive PostgreSQL or MySQL work isolated to the database adapter layer. The proof modules for those targets are test-only; runtime code still rejects PostgreSQL and MySQL target names.
Config Has A Boundary
Use src/config for source-level app defaults and auth policy that app code
imports directly. App identity, default authenticated navigation, protected
routes, app roles, permission values, and banned-session copy belong there.
Use wrangler.jsonc as the committed source of truth for non-secret Worker
runtime values. Typical values include EMAIL_PROVIDER, EMAIL_FROM,
EMAIL_REPLY_TO, BETTER_AUTH_URL, and MAILGUN_DOMAIN.
Use .dev.vars for local secret values and local-only overrides. Use Wrangler
secrets for deployed secret values. Do not commit API keys, auth secrets, or
provider credentials in wrangler.jsonc.
Server First
Keep auth, database writes, email, and validation on the server.
Use client JavaScript only where it improves a specific interaction.
Validate At The Boundary
Use Zod for request bodies, form input, and action input.
Keep validation close to the route or action that receives external data.
Middleware Owns Auth State
Middleware creates the Better Auth instance, reads the session, and writes:
Astro.locals.userAstro.locals.sessionAstro.locals.isAuthenticated
Pages and routes should read from locals instead of reimplementing session lookup.
Routes Are Public By Default
Middleware loads auth state for every request, but route protection is opt-in.
Use src/config/auth.ts when pages or API namespaces should be consistently
protected by middleware. Use route-local checks when a page or API handler needs
custom redirect or JSON 401 behavior.
Keep Better Auth endpoints under /api/auth public so sign in, sign up,
verification, reset, session, callback, and sign-out requests can reach Better
Auth before a user has a session.
Roles Are App Policy
The Better Auth admin plugin is installed and configured with admin,
moderator, user, and banned roles. App permissions live in
src/config/auth.ts, and local checks should use the helpers in
src/auth/permissions.ts.
Email Is A Provider
Auth email is rendered once and sent through a provider.
Local development can use console. Workers deployments should use Cloudflare
Email, Resend, Mailgun, or another fetch/binding-based provider.
Use sendEmail directly for custom transactional messages. Use
createAuthEmailSenderFromEnv for Better Auth verification and reset flows so
auth email templates and EMAIL_FROM handling stay centralized.
Initialization Is Operational
Run migrations before seeding users. npm run init:admin creates a verified
Better Auth user directly in D1 through Wrangler, selecting local or remote D1
from BETTER_AUTH_URL unless --local or --remote is passed.
Keep The Boilerplate Small
Verge Kit does not include uploads, media processing, full admin CRUD screens, analytics, queues, workflows, or production PostgreSQL/MySQL runtime support yet.
Add those when an application needs them.