Yielded Auth
Authentication that fits your Effect application.
Schema for the contract. Layers for your backend. Effect Atom for the client. Passwords, passkeys, codes, and OAuth with your accounts, your database, and your policies.
One contract, server to client
Section titled “One contract, server to client”Describe your session claims and the actions clients may call with Effect Schema. The server, HTTP routes, and client share that definition.
import { Schema } from "effect";import { AuthContract } from "@yielded/auth";
export const AuthApi = AuthContract.make("app/Auth", { claims: Schema.Struct({ displayName: Schema.String }), actions: (sessions) => ({ signIn: AuthContract.passwordSignIn(sessions) }),});- Server handler
yield* auth.signIn({ email, password }) - HTTP route
POST /auth/signIn - Client Effect
yield* client.auth.signIn({ email, password }) - React
const [result, signIn] = useAtom(auth.signIn)
Inputs and public results use the same schemas. Expected failures stay typed; credentials travel through the private HTTP boundary. Clients reach only the actions you declare.
An ordinary Effect service
Section titled “An ordinary Effect service”Choose your methods and session behavior, then supply their dependencies with
Layers. Inside a handler, yield* AppAuth gives you auth alongside your other
application services.
import { Auth, Http, Password, Sessions } from "@yielded/auth";
import { AuthApi } from "@app/domain/auth-contract";
export const AppAuth = Auth.make(AuthApi, { sessions: Sessions.stateful({ maxAge: "8 hours", idleTimeout: "30 minutes" }), strategies: { password: Password.make() }, defaultStrategy: "password",});
export const AuthRoutes = Http.layer(AppAuth, { origin: "https://app.example.com" });Provide storage, account policy, hashing, and keys to AuthRoutes; its Layer type
shows what is still needed. Your app owns account creation and authorization.
See how Auth fits into Effect, or
add it to an existing HttpApi.
Effect on the client too
Section titled “Effect on the client too”Derive an Effect HttpClient service and atoms from the shared contract:
import { Atom as AuthAtom, Client } from "@yielded/auth";
import { AuthApi } from "@app/domain/auth-contract";
export const AppClient = Client.make(AuthApi, { baseUrl: "https://app.example.com" });export const auth = AuthAtom.make(AppClient);Read auth.session and dispatch auth.signIn or auth.signOut with ordinary
@effect/atom-react hooks. Auth mutations refresh auth queries automatically.
Compose workflows in Effect and connect your application’s queries through
reactivity keys. Build the client.
Your accounts, your storage
Section titled “Your accounts, your storage”Keep your customer or employee model. Use managed auth tables, map your own SQL schema, or supply storage services for a different backend. Changing storage Layers keeps the contract and client intact.
Managed tablesPersistence. | Your schemaPersistence. | Your servicesLayer. | |
|---|---|---|---|
| Account table | YouYour table and IDs, mapped by column. | YouYour table and IDs, mapped by column. | YouYour records and IDs, in any store. |
| Auth tables and migrations | Yielded AuthDefined for you. Drizzle Kit generates migrations you review. | YouYour table names, columns, and migrations. | YouYour durable store; SQL is optional. |
| Queries and transactions | Yielded AuthRun for you. | Yielded AuthRun against your tables, checked at startup. | YouYour implementation of each storage service. |
| Sign-in workflows | Yielded AuthRun for you. | Yielded AuthRun for you. | Yielded AuthRun for you, on your storage. |
| Contract and client | UnchangedThe same AuthApi, AppAuth, and client at every level. Only Layers change. | ||
| Runnable app | Managed Drizzle | Custom Drizzle, Effect SQL | Custom services |
Managed tables
Persistence.managed(…)- Account table
- You
- Your table and IDs, mapped by column.
- Auth tables and migrations
- Yielded Auth
- Defined for you. Drizzle Kit generates migrations you review.
- Queries and transactions
- Yielded Auth
- Run for you.
- Sign-in workflows
- Yielded Auth
- Run for you.
Your schema
Persistence.map(…)- Account table
- You
- Your table and IDs, mapped by column.
- Auth tables and migrations
- You
- Your table names, columns, and migrations.
- Queries and transactions
- Yielded Auth
- Run against your tables, checked at startup.
- Sign-in workflows
- Yielded Auth
- Run for you.
Your services
Layer.mergeAll(…)- Account table
- You
- Your records and IDs, in any store.
- Auth tables and migrations
- You
- Your durable store; SQL is optional.
- Queries and transactions
- You
- Your implementation of each storage service.
- Sign-in workflows
- Yielded Auth
- Run for you, on your storage.
Contract and client
UnchangedThe same
AuthApi,AppAuth, and client at every level. Only Layers change.
The database and backend guide explains the choices and the durability each implementation must provide. Four runnable account apps show the same workflows across Drizzle, Effect SQL, and a non-SQL store.
Add the methods your application needs
Section titled “Add the methods your application needs”| Method | What you can build |
|---|---|
| Passwords | Registration, sign-in, and recovery. |
| Passkeys | WebAuthn sign-in and credential management. |
| Email codes & magic links | Passwordless sign-in and address verification. |
| Phone codes | SMS sign-in and number verification. |
| Two-factor authentication | Authenticator apps after a first factor. |
| OAuth & OIDC | Provider sign-in, account linking, and retained API access. |
Each guide shows the strategy, the services you supply, and the calls you make. Start with GitHub or Google for provider setup.