A backend. A database. A storage bucket.
That's a complete platform.
@justwant/* is a TypeScript-first library ecosystem that covers authentication, observability, billing, notifications, file storage, and much more — using infrastructure you already own.
import { createAudit } from '@justwant/audit'
import { integrityPlugin } from '@justwant/audit/plugin-integrity'
import { pgAdapter } from '@justwant/audit/adapter-pg'
const audit = createAudit({
adapter: pgAdapter(pool),
plugins: [integrityPlugin()],
})With a backend, a database, and a storage bucket, you now have:
Authentication · Permissions · Consent · Audit trail · Observability · Analytics · File storage · Notifications · Webhooks · Rate limiting · Feature flags · API key management · Scheduled jobs · Task queues · Billing · CMS · Session replay · Onboarding · Real-time · Data pipeline · Waitlist
No vendor lock-in. No data leaving your infrastructure. No third-party terms applied to your users.
Small, focused packages with no inter-package dependencies. Everything else is built on top of these.
| Package | Role |
|---|---|
@justwant/meta |
Type primitives. Inspectable<N> (named config objects), Definable<N> (callable factories), RefLike<T> (entity references) |
@justwant/db |
Data Access Layer. Contracts, Drizzle, Prisma, Waddler. defineContract(), AdapterError, createDrizzleAdapter |
@justwant/plugin |
Plugin system. createPlugin(), dependency graph, declaration merging |
@justwant/id |
ID generation. ulid(), uuid(), prefixed('key') → key_01J8X |
@justwant/crypto |
HMAC, hash, sign, verify, encrypt, decrypt |
@justwant/env |
Typed environment variables. Zod schema, coercion, expansion, redaction |
@justwant/lock |
Distributed locks. acquire(key, fn, { ttl }) |
@justwant/retry |
Retry with backoff. Exponential, linear, and fixed strategies |
@justwant/event |
Internal event bus. Decouples packages from each other |
@justwant/context |
Request context propagation via AsyncLocalStorage |
@justwant/cookie |
Cookie read/write. Signed, httpOnly, sameSite, __Host- prefix |
@justwant/config |
Multi-source config with waterfall resolution. get(), watch, cache |
Packages that combine foundation primitives into reusable cross-cutting concerns.
| Package | Role |
|---|---|
@justwant/job |
Scheduled jobs. Pluggable runners (Node, Cloudflare, Vercel, QStash) |
@justwant/queue |
Event-triggered jobs. Steps, durability, fan-out, sleep |
@justwant/storage |
File upload/download. Multipart, lifecycle, signed URLs, scan, transform |
@justwant/protect |
HTTP security. Rate limiting, IP intelligence, bot detection, WAF |
@justwant/flag |
Feature flags. Typed evaluation, rollout, targeting, A/B |
@justwant/preference |
User preferences. Namespaced, typed, global → plan → user inheritance |
@justwant/consent |
GDPR consent. History, versioning, legal proof, expiry, right to erasure |
@justwant/permission |
RBAC/ABAC. Roles, ownership, delegation, hierarchy, scope |
@justwant/audit |
Immutable event log. HMAC chaining, redaction, retention, export |
@justwant/webhook |
Outbound webhooks. Signing, retry, dead-letter, delivery tracking |
@justwant/notify |
Multi-channel notifications. Templates, routing, digest, deduplication |
Higher-level packages that expose direct product value, built entirely on top of the two groups above.
| Package | Replaces | What it does |
|---|---|---|
@justwant/auth |
Auth0, Clerk | Sessions, OAuth 40+, 2FA, passkeys, organizations, SCIM |
@justwant/keys |
Unkey, Zuplo | Hashed API keys, per-key rate limits, credits, rotation |
@justwant/analytics |
Plausible, Mixpanel | Events, sessions, funnels, retention, privacy-first |
@justwant/monitor |
Sentry, Bugsnag | Error tracking, performance, source maps, alerting |
@justwant/billing |
Stripe Billing, Paddle | Plans, credits, usage-based billing, trials, dunning |
@justwant/cms |
Contentful, Sanity | Typed schemas, CRUD, versioning, preview, i18n, media |
@justwant/support |
Intercom, Crisp | Conversations, tickets, agents, automatic user context |
@justwant/onboarding |
Userflow, Appcues | Steps, progress tracking, nudges, completion hooks |
@justwant/waitlist |
Custom solutions | Sign-up, referral, position, batch invitations |
@justwant/pipeline |
Segment, RudderStack | Sources → transforms → destinations, event fan-out |
@justwant/feature |
PostHog, Hotjar | Session replay, heatmaps, surveys, breadcrumbs |
Every package that touches persistence accepts an adapter. You bring the database — the package brings the logic.
import { createAudit } from '@justwant/audit'
import { prismaAdapter } from '@justwant/audit/adapter-prisma'
import { drizzleAdapter } from '@justwant/audit/adapter-drizzle'
import { pgAdapter } from '@justwant/audit/adapter-pg'
// Pick what matches your stack
const audit = createAudit({ adapter: prismaAdapter(prismaClient) })
const audit = createAudit({ adapter: drizzleAdapter(db, { schema }) })
const audit = createAudit({ adapter: pgAdapter(pool) })
// Or implement the contract directly for anything else
const audit = createAudit({
adapter: {
async insert(event) { /* your logic */ },
async findMany(filters) { /* your logic */ },
},
})Each package has a minimal core. Features are opt-in plugins — imported explicitly, so bundlers only include what you actually use.
import { createAudit } from '@justwant/audit'
import { integrityPlugin } from '@justwant/audit/plugin-integrity'
import { retentionPlugin } from '@justwant/audit/plugin-retention'
import { streamPlugin } from '@justwant/audit/plugin-stream'
import { pgAdapter } from '@justwant/audit/adapter-pg'
const audit = createAudit({
adapter: pgAdapter(pool),
plugins: [
integrityPlugin(),
retentionPlugin({ after: '90d', action: 'anonymize' }),
streamPlugin({ destination: webhookAdapter() }),
],
})Adapters and plugins are isolated subpath exports. Your bundler only loads what you import — nothing else is included.
// Only these files end up in your bundle
import { createAudit } from '@justwant/audit'
import { integrityPlugin } from '@justwant/audit/plugin-integrity'
import { pgAdapter } from '@justwant/audit/adapter-pg'
// Other adapters are never loaded, never bundled
// @justwant/audit/adapter-prisma
// @justwant/audit/adapter-drizzlePlugins extend types without patching the core. The result is always fully typed, inferred directly from your config.
// With creditsPlugin and rateLimitPlugin active on @justwant/keys:
const result = await keys.verify('sk_live_abc123')
result.valid // always present
result.credits.remaining // typed — only when creditsPlugin is active
result.rateLimit.reset // typed — only when rateLimitPlugin is active
result.permissions // typed — only when permissionPlugin is active# Add the packages you need
pnpm add @justwant/auth @justwant/audit
# Peer dependencies — install only what your adapters require
pnpm add drizzle-orm # Drizzle adapters# Generate SQL migrations for all active packages
npx justwant migrate generate --dialect postgres
# For your ORM
npx justwant migrate generate --adapter prisma # outputs Prisma model blocks
npx justwant migrate generate --adapter drizzle # outputs table definitions@justwant/
├── packages/
│ ├── meta/ # Foundation
│ ├── adapter/
│ ├── plugin/
│ ├── id/
│ ├── crypto/
│ ├── env/
│ ├── cache/
│ ├── lock/
│ ├── retry/
│ ├── event/
│ ├── context/
│ ├── cookie/
│ ├── config/
│ │
│ ├── job/ # Building blocks
│ ├── queue/
│ ├── storage/
│ ├── protect/
│ ├── flag/
│ ├── preference/
│ ├── consent/
│ ├── permission/
│ ├── audit/
│ ├── webhook/
│ ├── notify/
│ │
│ ├── auth/ # Features
│ ├── keys/
│ ├── analytics/
│ ├── monitor/
│ ├── billing/
│ ├── cms/
│ ├── support/
│ ├── onboarding/
│ ├── waitlist/
│ ├── pipeline/
│ └── feature/
│
├── docs/
└── examples/ # Next.js, Nuxt, Hono, Express
Dependency rule: Foundation packages import nothing from this repo. Building blocks import Foundation only. Features import both — but never each other. Cross-feature communication goes through @justwant/event.
This is a pnpm workspace monorepo.
pnpm install # install all dependencies
pnpm build # build all packages
pnpm test # run all tests
cd packages/db && pnpm dev # work on a single packageEach package has its own CONTRIBUTING.md with adapter and plugin authoring guidelines.
MIT — see LICENSE