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 (Userusers, Categorycategories)

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.