effect-auth

Quick Start

Run the maintained effect-auth Cloudflare example and trace its production-shaped integration.

This path runs the example used by release smoke checks: a TanStack Start app Worker proxies same-origin /auth/* requests to a dedicated effect-auth Worker backed by D1 and Durable Object rate limiting. Local auth email goes to a D1 outbox, so no external provider is needed.

You will verifyConcrete flow
Passwordless sign-inRequest a magic link, open it from the local outbox, receive a session cookie
Protected applicationOpen the private documents workspace and create an app-owned resource
Account recoveryComplete password reset through the local development outbox
Runtime boundariesApp Worker, auth Worker, service binding, D1, rate limiter, and email adapter

Run locally

You need Git and Bun 1.3 or newer. From a directory where you keep projects:

git clone https://github.com/nr1brolyfan/effect-auth.git
cd effect-auth
bun install
AUTH_EMAIL_FROM=demo@example.com \
AUTH_PUBLIC_URL=http://localhost:3000 \
bun run --filter tanstack-cloudflare-auth-split dev:local

Then complete one realistic product flow:

  1. Open http://localhost:3000 and choose Magic link.
  2. Open /dev-email-outbox and follow the newest generated link.
  3. Open /documents and create a private document.
  4. Sign out and complete a password reset through the local outbox.

Password sign-in intentionally enters the demo login-approval flow. The Google, Discord, and GitHub buttons are placeholders; use magic link for the shortest successful path. The outbox and approval screen are development UX, not production authorization or mail delivery.

Run the same core path automatically with:

AUTH_EMAIL_FROM=demo@example.com \
AUTH_PUBLIC_URL=http://localhost:3000 \
bun run --filter tanstack-cloudflare-auth-split smoke:local

The smoke test covers magic link, password reset, login approval delivery, session persistence, and cleanup.

Trace the request

The app keeps browser auth same-origin while a dedicated Worker owns auth infrastructure

The split topology keeps app/SSR work in one Worker and secrets, auth storage, and rate limiting in another. The app route forwarding the contract is deliberately small:

src/routes/auth/$.ts
export const Route = createFileRoute("/auth/$")({
  server: {
    handlers: {
      GET: ({ request }) => env.AUTH_BACKEND.fetch(request),
      POST: ({ request }) => env.AUTH_BACKEND.fetch(request),
    },
  },
});

The browser client stays same-origin and decodes the standard preset contract:

src/auth/client.ts
import { createAuthClient } from "@effect-auth/core/Client";

export const authClient = createAuthClient();

const session = await authClient.session.currentOrUndefined();

Origin allowlisting protects unsafe auth requests against CSRF; it does not add CORS headers. Prefer same-origin routing unless your deployment requires a separate browser-visible auth origin.

Read the implementation

ConcernMaintained source
Cloudflare resourcesalchemy.run.ts
Auth Layer graphsrc/server/auth.ts
Auth Worker entrysrc/workers/auth-backend.ts
Same-origin routesrc/routes/auth/$.ts
Typed browser clientsrc/auth/client.ts
Sign-in and session UIsrc/routes/index.tsx
Protected domain workflowsrc/server/documents.ts

Use the files as a dependency and ownership map, not a blind copy: select only the features your public contract mounts, preserve your framework conventions, and supply every dependency reported by the resulting Layer type.

Adapt it to your application

  1. Install pinned core, Effect, and adapter packages.
  2. Select the authentication features and HTTP endpoints your application needs.
  3. Apply the migration array matching your database before traffic.
  4. Build runtime Layers for storage, crypto, secrets, mail, rate limiting, and enabled features.
  5. Bind auth to the framework, create the matching client contract, and handle successful continuation states such as MFA or verification explicitly.
  6. Verify origin policy, cookies, migrations, email, abuse controls, and recovery using the Production Checklist.
Local exampleProduction replacement
D1 development databaseManaged D1 with backups, retention, migration ledger, and recovery testing
D1 email outboxCloudflare Send Email or an application-owned AuthMailer implementation
Example secret fallbackUnique protected secret material per environment; never commit or log it
Demo login approval UIApp-authorized, audited review policy or removal of the feature
Secure __Host- cookies on localhostHTTPS with the same secure cookie profile and an exact public origin

Using a coding agent

Give the agent /llms.txt, require public package subpaths, and have it inspect your runtime, database, user model, and installed versions before proposing changes. It should ask which features you need, choose the integration boundary per endpoint, preserve your architecture, and run your repository checks.

On this page