Standards Docs
Concepts

Records

Runtime instances of objects: how to fetch, create, update, and delete them with React hooks.

Records are the runtime instances of objects. The React hooks in @stndrds/react load and mutate them.

// @noverify
import { useCreateRecord, useRecords } from "@stndrds/react";

function ContactList() {
  const { data: contacts, isLoading } = useRecords("contacts");
  const create = useCreateRecord("contacts");

  if (isLoading) return null;

  return (
    <ul>
      {contacts?.data.map((c) => (
        <li key={c.id}>{c.values.firstName}</li>
      ))}
    </ul>
  );
}

useRecords takes the object name as a positional string argument, not a config object. The response is { data: ObjectRecord[], total: number }.

Breaking in vNEXT: the TypedRecord and BaseRecord aliases are gone — ObjectRecord<TValues> is now the single record type (generic on its values). Replace TypedRecord / BaseRecord imports with ObjectRecord. Date fields on a returned record (createdAt, updatedAt, deletedAt) are now hydrated to Date objects rather than ISO strings.

Hook surface

HookUse case
useRecordfetch one record by id
useRecordsfetch a list
useSearchRecordstext search
useInfiniteSearchRecordspaginated search
useCreateRecordcreate
useUpdateRecordupdate
useDeleteRecorddelete single (soft — moves to archive)
useRestoreRecordrestore a soft-deleted record
usePurgeRecordpermanently destroy a soft-deleted record
useBulkDeleteRecordsbulk delete
useObject / useObjectsfetch object definitions
useMyProfilecurrent actor
useSchemaClientdirect client access (escape hatch)

Query keys

Always use the recordsKeys factory from @stndrds/react when interacting with the query cache. Never write ad-hoc key arrays — the factory guarantees that invalidations cover all cache shapes (list, detail, grid, kanban).

// @noverify
import { recordsKeys } from "@stndrds/react";
import { useQueryClient } from "@tanstack/react-query";

const queryClient = useQueryClient();
queryClient.invalidateQueries({
  queryKey: recordsKeys.list("contacts"),
});

Available keys: all, lists, list, details, detail, grids, grid, kanbans, kanban, search, searchInfinite.

Optimistic updates

Optimistic update logic lives in @stndrds/react hooks (useUpdateRecord.onMutate). The pattern snapshots all relevant caches, applies the update immediately, and rolls back on error. Do not replicate this logic in @stndrds/ui components.

Optimistic updates belong in @stndrds/react, never in @stndrds/ui. The useRecordSave hook in @stndrds/ui is a thin wrapper — it does not touch the query cache.

Create and update now reject unknown attribute keys with HTTP 400 (ValidationError listing every offending key). Previously, unknown keys were silently persisted. If you pass validate: false, unknown keys are stripped instead of rejected — but the storage layer drops them either way. Make sure your payloads only carry attributes declared on the object.

Deletion is now a soft-delete: useDeleteRecord archives the record (sets deletedAt) and cascade-archives its edges. Restore via useRestoreRecord — only cascade-tagged edges wake up; edges independently archived stay archived. To permanently destroy a record, soft-delete it first, then call usePurgeRecord (requires manage permission).

On this page