Skip to Content

Business apps from one typed config.

Declare collections with fields, access rules and hooks. Quickben gives you a typed server API, REST routes and an admin UI on your own database. Built for the Next.js App Router.

  • Alpha
  • Apache-2.0
  • TypeScript, ESM, Node.js 22+
quickben.config.ts
import { defineCollection, defineConfig, devAuth, fields as f } from "@quickben/core";
import { drizzleAdapter } from "@quickben/db-drizzle";
import { tenancy } from "@quickben/plugin-tenancy";

const users = defineCollection({
  slug: "users",
  fields: { email: f.email({ required: true, unique: true }) },
});

const posts = defineCollection({
  slug: "posts",
  labels: { singular: "Post", plural: "Posts" },
  fields: {
    title: f.text({ required: true, maxLength: 200 }),
    status: f.select({ options: ["draft", "published"], default: "draft" }),
    author: f.relation({ to: "users" }),
    publishedAt: f.date(),
    meta: f.json(),
  },
  access: {
    read: () => true,
    create: ({ user }) => !!user,
    update: ({ user }) => (user ? { author: { eq: user.id } } : false),
    delete: ({ user }) => user?.roles?.includes("admin") === true,
  },
  hooks: { beforeChange: [({ data }) => data] },
  admin: { useAsTitle: "title", defaultColumns: ["title", "status", "publishedAt"] },
});

export default defineConfig({
  db: drizzleAdapter({ dialect: "postgres", url: process.env.DATABASE_URL }),
  collections: [users, posts],
  plugins: [tenancy({ scope: ["posts"] })],
  auth: devAuth(),
});
  1. Document, input and filter types are inferred from these fields.
  2. Access rules return true, false or a filter. Filters are AND-ed with every query.
  3. Pick a database adapter. Your collections stay the same.
  4. Plugins are functions from config to config. They run in the order listed.

What you get

Typed collectionsAvailable

Document, create, update and filter types come from the field definitions. No code generation.

type Post = InferDoc<typeof posts>;
Access rules that return filtersAvailable

A rule returns true, false or a where filter. Reads AND the filter with the query. Writes must match it.

update: ({ user }) => ({ author: { eq: user.id } })
Database adaptersAvailable

One small adapter interface with a portable query model. In-memory for tests. Drizzle for Postgres, PGlite and SQLite, with drizzle-kit migrations.

db: drizzleAdapter({ dialect: "pglite", dataDir: "./.pglite" })
Two files in your Next.js appAvailable

A catch-all route handler for REST and a catch-all page for the admin. The admin page also defines the server function for saves.

app/api/[...quickben]/route.ts
app/admin/[[...segments]]/page.tsx
Admin generated from configAvailable

Dashboard, list, create and edit screens from your fields. The sidebar comes from collections and modules. No Tailwind setup in your app.

admin: { useAsTitle: "title" }
Plugins, including multi-tenancyPlanned

A plugin adds collections, hooks and modules. The tenancy plugin adds organizations, memberships and scoped access.

plugins: [tenancy({ scope: ["posts"] })]

The admin UI

Admin list view of posts with filters and pagination
List: columns, search, filters, sort.
Admin edit form of a post with relation fields
Edit: forms generated from fields.

Screens from the playground. Same config, same access rules as the REST API.

How it works

  1. Declare

    Collections, fields, access rules and hooks in quickben.config.ts.

    defineConfig({ db, collections })
  2. Call the local API

    Typed reads and writes on the server. Access and hooks run on every call.

    await qb.find("posts", { where }, { user })
  3. Serve REST and the admin

    Route handlers and admin pages call the same local API.

    createRouteHandlers(config)
    createAdminPage(config, { serverFunction })

Status

Quickben is alpha. APIs can change before 1.0. The code is open on GitHub under Apache-2.0, built and maintained by Vialabs.

Package status
PackageStatus
@quickben/coreAvailable
@quickben/db-memoryAvailable
@quickben/db-drizzleAvailable
@quickben/nextAvailable
@quickben/adminAvailable
@quickben/plugin-tenancyPlanned