Browse documentation

resource()

Every option on a resource, its columns, fields and filters.

Register one table or model as an admin resource.

export function resource<Ref, const Name extends string>(ref: Ref, options: ResourceOptions<InferRow<Ref>> & { name: Name; }): ResourceConfig<Ref, InferRow<Ref>, ResourceOptions<InferRow<Ref>> & { name: Name; }>;
export function resource<Ref>(ref: Ref, options: ResourceOptions<InferRow<Ref>>): ResourceConfig<Ref, InferRow<Ref>, ResourceOptions<InferRow<Ref>>>;

ref is whatever your adapter understands — a Drizzle table object, or a Prisma model name. The row type comes from InferRow<Ref>: a Drizzle table resolves through $inferSelect, a string ref through your FlowpanelResources augmentation, and anything else falls back to Record<string, unknown>. When it resolves to a real row type, columns, search, filters and defaultSort only accept real column names; when it falls back, they are plain string and the check moves to defineAdmin's introspect-time validation.

import { resource } from "@flowpanel/kit";
import { orders } from "@/db/schema";

export const ordersResource = resource(orders, {
  label: "Order",
  plural: "Orders",
  icon: "shopping-cart",
  columns: ["id", "customerEmail", { field: "total", format: "money" }, "status"],
  search: ["customerEmail"],
  filters: ["status", { field: "createdAt", type: "daterange" }],
  defaultSort: { field: "createdAt", dir: "desc" },
});

ResourceOptions

Prop

Type

Icons

ResourceOptions.icon, dashboard/page/queue icons, action icons and CommandItem.icon all use the same serializable IconName union. FlowPanel turns the name into a decorative Lucide SVG in the sidebar, tab strip and ⌘K palette, so the config remains safe to pass through a React Server Component boundary. Unknown names are rejected by TypeScript instead of disappearing at runtime. Built-in names include users, settings, layout-dashboard, database, shopping-cart, archive, refresh, play, ban and trash-2; editor autocomplete shows the complete IconName set.

For custom pages and slots, render the same registry directly:

import { FlowpanelIcon } from "@flowpanel/kit/react";

<FlowpanelIcon name="workflow" className="size-4" />;

ColumnDef

An entry in columns. A bare string is shorthand for { field: "name" }.

Prop

Type

field is optional so a column can render a value no row property holds — a join, something computed. Such a column must set both render and label, never sorts or filters, and is skipped by export; see Joined or computed values.

ColumnFormat

Declarative cell rendering — reach for this before writing a render function.

type ColumnFormat =
  | "badge"
  | "money"
  | "number"
  | { kind: "badge"; tones?: Record<string, Tone> }
  | { kind: "money"; currency?: string; scale?: number };

Tone is "default" | "accent" | "ok" | "warn" | "err" | "info" | "muted". The object form of badge maps each cell value to a tone:

{ field: "status", format: { kind: "badge", tones: { paid: "ok", failed: "err" } } }

FieldDef

An entry in create.fields, update.fields, a DetailTab, or an action's form. Every rule here is enforced on the server, not just in the UI.

Prop

Type

FieldType

type FieldType =
  | "text" | "textarea" | "number" | "email" | "password" | "url"
  | "date" | "datetime" | "time"
  | "boolean" | "switch" | "checkbox"
  | "select" | "multiselect" | "radio"
  | "json" | "markdown" | "tags" | "reference" | "hidden" | "color";

Omit it on a declared field and the control is "text" — or "reference" when the field sets reference. The adapter's ColumnMeta.type is consulted only by the fully generated form a resource gets when it declares no create.fields / update.fields at all, and even there it only maps number, boolean, date and json; every other column type renders as text. So enum, array and reference columns need an explicit type (plus options / reference) to get a richer control.

FilterDef

An entry in filters. A bare string is always a text filter — there is no inference from the column's type, so declare a FilterDef with an explicit type for a select, a date range, or anything else.

Prop

Type

FilterType

type FilterType =
  | "text" | "select" | "multiselect"
  | "daterange" | "numeric-range" | "boolean" | "tag";

daterange and numeric-range reach your adapter as a FilterRangeValue; multiselect as a FilterInValue. Both are documented under Contexts.

DetailTab

A tab on the full-page detail view at /<basePath>/<resource>/<id>.

Prop

Type

SelectOption

type SelectOption = { label: string; value: string | number | boolean };

Wherever options is accepted, you may pass string[], SelectOption[], or a function resolved per request.

ListResult

What a list returns, from the adapter through to the pagination control.

Prop

Type

ResourceConfig

What resource() returns. You pass it to defineAdmin; you rarely read it.

Prop

Type