Package Exports
- @geenius/adapters
- @geenius/adapters/convex
- @geenius/adapters/convex/api
- @geenius/adapters/react
- @geenius/adapters/react-css
- @geenius/adapters/shared
- @geenius/adapters/solidjs
- @geenius/adapters/solidjs-css
Readme
@geenius/adapters
The architectural lynchpin of the Geenius ecosystem — standardized adapter contracts that make backend services interchangeable with a one-file swap.
Overview
@geenius/adapters defines standard interfaces for six infrastructure domains and provides localStorage mock implementations for zero-config prototyping. Any frontend component talks exclusively to an adapter interface — never to a database or service directly.
This is what makes "swap Convex for Supabase" a single-file change instead of a months-long rewrite.
Architecture: Thin Contracts + Domain Packages
@geenius/adapters is the contract layer — it only defines what each service must do (the interfaces) and provides localStorage mocks for fast prototyping. Real provider implementations live in the dedicated domain packages:
| Domain | Interface | Mock (here) | Real Providers (domain package) |
|---|---|---|---|
| DB | DbAdapter |
localStorage |
@geenius/db → Convex, Supabase, Neon, MongoDB, CloudflareKV, Memory |
| Auth | AuthAdapter |
localStorage |
@geenius/auth → Better Auth, Convex Auth, Clerk, Supabase Auth |
| Payments | PaymentsAdapter |
localStorage, noop |
@geenius/payments → Stripe, LemonSqueezy, Polar |
| AI | AiAdapter |
localStorage |
@geenius/ai → OpenAI, Anthropic, Gemini, Ollama, CF AI Gateway, Vercel AI SDK |
| File Storage | FileStorageAdapter |
localStorage |
@geenius/file-storage → R2, S3, Uploadthing, Supabase Storage, Convex Storage, Minio |
| Admin | AdminAdapter |
localStorage |
(localStorage only for now) |
Installation
pnpm add @geenius/adaptersSub-package Exports
import { configureAdapters, createLocalStorageDbAdapter } from '@geenius/adapters' // shared (default)
import { AdapterProvider, useDb, useAuthAdapter, useAi } from '@geenius/adapters/react' // React hooks
import { AdapterProvider, createDb, createAuth } from '@geenius/adapters/solidjs' // SolidJS primitives
import { schema, createConvexAdapter } from '@geenius/adapters/convex' // Convex schema + client helper
import { AdaptersPage, AdapterCard } from '@geenius/adapters/react-css' // Styled React components
import { AdaptersPage, AdapterCard } from '@geenius/adapters/solidjs-css' // Styled SolidJS componentsQuick Start
1. Configure adapters at app startup
import { configureAdapters } from '@geenius/adapters'
// Call once before rendering
configureAdapters({
db: { provider: 'convex' },
auth: { provider: 'better-auth' },
ai: { provider: 'openai', apiKey: process.env.OPENAI_API_KEY },
storage: { provider: 'r2' },
payments: { provider: 'stripe' },
})2. Wrap your app with AdapterProvider (React)
import { AdapterProvider } from '@geenius/adapters/react'
import { createLocalStorageDbAdapter, createLocalStorageAuthAdapter } from '@geenius/adapters'
// Pronto tier — zero external deps
export function App() {
return (
<AdapterProvider
adapters={{
db: createLocalStorageDbAdapter(),
auth: createLocalStorageAuthAdapter(),
}}
healthCheck
>
<Router />
</AdapterProvider>
)
}For production (Lancio/Studio), keep the same AdapterProvider API and pass
real adapter instances from your own backend integration package.
@geenius/adapters provides the contract layer, the shared config helpers, and
the resolver registry. It does not bundle production backend adapters itself.
3. Use adapters in components
import { useAuthAdapter, useDb, useAi } from '@geenius/adapters/react'
export function Dashboard() {
const auth = useAuthAdapter()
const db = useDb()
const users = await db.list('users')
const session = await auth.getSession()
}Prototyping with localStorage (Pronto tier)
Every domain ships a localStorage implementation for zero-config prototyping:
import {
createLocalStorageAuthAdapter,
createLocalStorageDbAdapter,
createLocalStorageAiAdapter,
createLocalStorageFileAdapter,
createLocalStoragePaymentsAdapter,
createLocalStorageAdminAdapter,
createNoopPaymentsAdapter,
} from '@geenius/adapters'These adapters persist data in the browser's localStorage with no external dependencies. Upgrade to real adapters by swapping one factory call.
Where are the real providers?
| Domain | Package | Example |
|---|---|---|
| AI | @geenius/ai |
AIClient, memory, skills, tool calling, content templates |
| Auth | @geenius/auth |
AuthProviderAdapter with MFA, passkeys, API keys, RBAC, session management |
| Payments | @geenius/payments |
PaymentProviderAdapter with webhooks, invoices, customer portal, plan sync |
| File Storage | @geenius/file-storage |
R2, S3, Uploadthing, Supabase Storage, Convex Storage, Minio |
These domain packages implement the contracts defined here and extend them with rich, production-grade features.
Tier Gating
import { isFeatureAvailable, isPackageAvailable, getUpgradeFeatures } from '@geenius/adapters'
isFeatureAvailable('admin', 'pronto') // → false
isFeatureAvailable('admin', 'lancio') // → true
isFeatureAvailable('ai-magic', 'studio') // → true
getUpgradeFeatures('pronto', 'lancio')
// → ['admin', 'payments', 'blog', 'file-storage', 'ai-workflow', 'ai-embeddings']Provider Registry
import { PROVIDER_REGISTRY, getProvidersForDomain, getProviderMeta } from '@geenius/adapters'
getProvidersForDomain('ai')
// → [{ id: 'localStorage', tier: 'pronto' }, { id: 'openai', tier: 'lancio' }, ...]
getProviderMeta('payments', 'stripe')
// → { id: 'stripe', name: 'Stripe', domain: 'payments', tier: 'lancio', ... }Error Handling
All adapter methods throw structured GeeniusError instances to map underlying service exceptions to unified error classes (e.g. NotFoundError, UnauthorizedError).
View the Complete Error Handling Guide for how exceptions map to unified errors.
Adapter Interface Contracts
All interfaces are async (Promise-based), generic, and framework-agnostic. Swapping a provider only requires replacing the adapter factory call — no changes to consumers.
// DbAdapter — generic, collection-based
interface DbAdapter {
create<T>(collection: string, data: Omit<T, 'id'>): Promise<T & { id: string }>
get<T>(collection: string, id: string): Promise<T | null>
update<T>(collection: string, id: string, data: Partial<T>): Promise<T | null>
delete(collection: string, id: string): Promise<boolean>
list<T>(collection: string, options?: ListOptions): Promise<T[]>
query<T>(collection: string, filter: QueryFilter): Promise<T[]>
count(collection: string, filter?: QueryFilter): Promise<number>
}
// AuthAdapter — minimal contract (see @geenius/auth for MFA, passkeys, etc.)
interface AuthAdapter {
signIn(email: string, password: string): Promise<AuthSession>
signUp(email: string, password: string, name?: string): Promise<AuthSession>
signInWithOAuth(provider: OAuthProvider, options?: { redirectUrl?: string }): Promise<{ url: string }>
signOut(): Promise<void>
getSession(): Promise<AuthSession | null>
getUser(): Promise<AuthUser | null>
updateUser(updates: Partial<Pick<AuthUser, 'name' | 'image'>>): Promise<AuthUser | null>
}
// AiAdapter — minimal contract (see @geenius/ai for memory, skills, tools)
interface AiAdapter {
chat(messages: ChatMessage[], options?: AiOptions): Promise<ChatResponse>
complete(prompt: string, options?: AiOptions): Promise<string>
embed(text: string | string[]): Promise<number[][]>
stream(messages: ChatMessage[], options?: AiOptions): AsyncIterable<string>
}Tier Availability
| Tier | Description |
|---|---|
| Pronto | Prototype-ready. localStorage only. Zero external deps. |
| Lancio | Production-ready. Real backends via domain packages. |
| Studio | Full ecosystem. All Lancio providers + AI Magic, Analytics, Teams, and more. |
License
MIT — © Mehdi Nabhani