VVibeFlui

Registry

The VibeFlui registry maps schema string keys to runtime behavior.

Schemas stay JSON-friendly. Runtime code owns functions, React components, validators, handlers, option loaders, permissions, message resolvers, computed values, and class name resolvers.

Why registry exists

Do not put functions inside schemas.

schemas/users/bad-user.schema.ts

TS
export const badSchema = {
  resource: "users",
  form: {
    fields: [
      {
        name: "email",
        validator: (value: string) => value.includes("@")
      }
    ]
  }
};

Use a registry key instead.

schemas/users/good-user.schema.ts

TS
export const goodSchema = {
  version: "1.0.0",
  resource: "users",
  form: {
    fields: [
      {
        name: "email",
        validator: "users.email"
      }
    ]
  }
} as const;

Register the function in runtime code.

lib/vibeflui/registry.ts

TS
import { createRegistry } from "@vibeflui/core";

export const registry = createRegistry({
  validators: {
    "users.email": (value) => {
      return /@/.test(String(value)) ? undefined : "Enter a valid email address.";
    }
  }
});

Runtime registry slots

SlotUsed for
componentsCustom React components.
renderersCustom field, detail, or table cell renderers.
fieldAdaptersCustom form field implementations.
validatorsField validation functions.
transformersValue and response transformations.
actionHandlersAction execution handlers.
handlersHandler alias supported by runtime execution.
permissionResolversPermission decisions.
optionLoadersDynamic field or filter options.
hooksLifecycle hooks.
eventsEvent handlers.
classNameResolversDynamic class name resolution.
messageResolversMessage resolution.
computedResolversComputed field and column values.

Schema registry declaration

The schema can declare which registry keys it expects.

schemas/users/users.schema.ts

TS
export const usersSchema = {
  version: "1.0.0",
  resource: "users",
  registry: {
    renderers: ["users.statusBadge"],
    fieldAdapters: ["react-select"],
    validators: ["users.email"],
    transformers: ["users.trimString"],
    actionHandlers: ["users.create", "users.delete"],
    permissionResolvers: ["users.canDelete"],
    optionLoaders: ["roles.options"],
    hooks: ["users.beforeCreate"],
    events: ["users.formSubmitSucceeded"],
    classNameResolvers: ["users.tableRowClassName"],
    messageResolvers: ["users.messages"],
    computedResolvers: ["users.displayName"]
  }
} as const;

The declaration helps inspection and documentation. The runtime functions still belong in createRegistry() or FluiKitProvider.

Runtime setup

app/users/page.tsx

TSX
"use client";

import { FluiKit, FluiKitProvider, createRegistry } from "@vibeflui/core";
import { usersSchema } from "@/schemas/users.schema";

const registry = createRegistry({
  validators: {
    "users.email": (value) => {
      return /@/.test(String(value)) ? undefined : "Enter a valid email address.";
    }
  },
  optionLoaders: {
    "roles.options": async () => [
      { label: "Admin", value: "admin" },
      { label: "Editor", value: "editor" }
    ]
  },
  actionHandlers: {
    "users.create": async ({ values }) => {
      return {
        status: true,
        code: 200,
        message: `${String(values?.name ?? "User")} created`
      };
    }
  }
});

export default function UsersPage() {
  return (
    <FluiKitProvider registry={registry}>
      <FluiKit schema={usersSchema} />
    </FluiKitProvider>
  );
}

Provider shortcut

FluiKitProvider can receive a registry object or individual registry slots.

app/users/page.tsx

TSX
<FluiKitProvider
  validators={{
    "users.email": (value) => {
      return /@/.test(String(value)) ? undefined : "Enter a valid email address.";
    }
  }}
>
  <FluiKit schema={usersSchema} />
</FluiKitProvider>

For examples, prefer a named registry object because it is easier to reuse across pages.

Merge behavior

Registries are merged in order. Later registry entries override earlier entries with the same key.

This matters when combining parent providers, plugins, adapter packages, and page-specific registry entries.

TXT
schemas/
  users.schema.ts
lib/
  vibeflui/
    registry.tsx
app/
  users/
    page.tsx

Keep schemas declarative. Keep registry functions in runtime code.