Skip to content

Register a model ​

ts
admin.register("User");
admin.register("Post", { listDisplay: ["title", "author", "published"] });

The first argument is the model or entity name in your ORM — PascalCase, exact. The second argument is optional. Every key on it is optional.

register is synchronous. It stores intent. Validation and default-filling happen in mount.

Zero config ​

admin.register("User") still works. At mount the library picks:

ConcernDefault
Display labelFirst unique string among name, title, label, username, slug, email; else any unique string; else first string; else the id
List columnsDisplay field first, then other non-id scalars, up to 6, then createdAt if present
SearchNon-id string scalars (not FK scalars)
FiltersNone — configure listFilter explicitly
SortcreatedAt descending, or the id
Page size50
PermissionsAny authenticated admin
URL slugSimple English plural (User → users, Category → categories)

Reach for the second argument when those defaults are wrong — not before.

The step-by-step for putting this in your server file is Wire it into your app. That page walks through the same register() object as the published example.

What you can customize ​

ts
admin.register("Post", {
  listDisplay: ["title", "author", "published", "createdAt"],
  listFilter: ["published", "createdAt"],
  searchFields: ["title", "content"],
  defaultSort: { field: "createdAt", direction: "desc" },
  perPage: 25,
  displayField: "title",
  pluralName: "posts",
  fields: {
    content: { readOnly: true },
  },
  permissions: {
    delete: ["SUPER_ADMIN"],
  },
  scope: async (adminUser) =>
    adminUser.isSuperAdmin
      ? {}
      : { tenantId: adminUser.tenantId ?? "__no_tenant__" },
});

Full table: register() reference.

Validation at mount ​

These throw with the available names so a typo does not become a silent empty column:

  • Model does not exist in the adapter’s introspected models
  • listDisplay / fields / displayField names that are not on the model
  • searchFields that are not strings
  • listFilter fields that are not filterable
  • register() after mount()
  • mount() twice

Composite primary keys and models with no id are skipped with a warning across all adapters. They cannot be registered in this release.

Only registered models appear ​

A model in the schema is invisible to the admin until you register it. The Prisma example has Tenant and AdminAuditLog in the schema and never registers them — so they never show in the sidebar.

Released under the MIT License.