OSS-first docs

These docs teach the open system first: contracts, generated surfaces, runtimes, governance, and incremental adoption. Studio shows up as the operating layer on top, not as the source of truth.

AI index

Build guide

Implement entity lists, details, and edits with ContractSpec surfaces.

Use one contract-driven DataView for search, filters, result cards or rows, detail opening, and host-owned editing. UseEntityWorkspace for product-shell entity surfaces when you need native-paired workspace chrome, neutral token-backed metrics, evidence blocks, detail panels, and host edit slots. KeepDataViewRenderer for renderer-specific examples and lower-level collection composition.

1. Author the entity DataView

Keep list, grid, table, search, filter, pagination, and personalization defaults in the DataView contract. Link operations throughsource.primary, source.mutations, and action operation refs instead of adding a direct DataView-to-FormSpec field.

import { defineDataView } from '@lssm-tech/lib.contracts-spec/data-views';

export const CustomerWorkspaceView = defineDataView({
  meta: {
    key: 'crm.customers.workspace',
    version: '1.0.0',
    title: 'Customers',
    description: 'Search, review, and update CRM customer records.',
    domain: 'crm',
    entity: 'customer',
    owners: ['@crm'],
    tags: ['crm', 'customers'],
    stability: 'stable',
  },
  source: {
    primary: { key: 'crm.customers.list', version: '1.0.0' },
    mutations: {
      create: { key: 'crm.customers.create', version: '1.0.0' },
      update: { key: 'crm.customers.update', version: '1.0.0' },
    },
  },
  view: {
    kind: 'table',
    fields: [
      { key: 'name', label: 'Name', dataPath: 'name', sortable: true },
      { key: 'owner', label: 'Owner', dataPath: 'ownerRef' },
      { key: 'arr', label: 'ARR', dataPath: 'arr', format: { type: 'currency', currency: 'EUR' } },
      { key: 'notes', label: 'Notes', dataPath: 'notes', visibility: { minDataDepth: 'detailed' } },
    ],
    columns: [{ field: 'name' }, { field: 'owner' }, { field: 'arr' }],
    collection: {
      viewModes: { defaultMode: 'table', allowedModes: ['list', 'grid', 'table'] },
      toolbar: { search: true, filters: true, viewMode: true, density: true, dataDepth: true },
      pagination: { pageSize: 25, pageSizeOptions: [10, 25, 50] },
      personalization: { enabled: true, persist: { viewMode: true, density: true, dataDepth: true, pageSize: true } },
    },
  },
});

2. Render searchable results

Resolve user preferences in the host, then pass ordinary props to the renderer. Treat card clicks, row clicks, and explicit detail actions as the same semantic open-detail event so analytics and keyboard behavior stay coherent.

import { DataViewRenderer } from '@lssm-tech/lib.design-system';
import { resolveDataViewPreferences } from '@lssm-tech/lib.personalization/data-view-preferences';

const resolved = resolveDataViewPreferences({ spec: CustomerWorkspaceView, preferences, insights });

<DataViewRenderer
  spec={CustomerWorkspaceView}
  items={customers}
  defaultViewMode={resolved.viewMode}
  defaultDensity={resolved.density}
  defaultDataDepth={resolved.dataDepth}
  pagination={{ page, pageSize: resolved.pageSize ?? 25, total }}
  onSearchChange={(search) => track({ action: 'search_changed', search })}
  onFilterChange={(filters) => track({ action: 'filters_changed', filters })}
  onRowClick={(item) => openDetail(item)}
/>;

3. Compose detail and edit panels

Use AdaptivePanel for responsive detail/edit panels andRichRef for reference-like fields. Resolve edit UI in this order: feature opToPresentation, feature forms, DataView mutations, DataView action operation refs, then a hostrenderFormSlot fallback with an explicit residual-risk note.

import { AdaptivePanel } from '@lssm-tech/lib.design-system/components/overlays';
import { RichRef } from '@lssm-tech/lib.ui-kit-web/rich-ref';

function CustomerDetailPanel({ customer, editForm }: Props) {
  if (!customer) return null;

  return (
    <AdaptivePanel
      open
      onOpenChange={close}
      trigger={<button type="button">Open customer</button>}
      title={customer.name ?? 'Customer detail'}
      mode="responsive"
    >
      <RichRef kindId="object" refId={customer.ownerRef} variant="inline" />
      {editForm ?? <p>Connect a host FormSpec slot for editing.</p>}
    </AdaptivePanel>
  );
}

4. Apply personalization and RoleMorph

Personalization

Use @lssm-tech/lib.personalization to seed view mode, density, data depth, and page size. Keep the design-system renderer portable by passing resolved props instead of importing personalization inside UI components.

RoleMorph

Resolve hidden fields, hidden or blocked actions, approval states, density, and data-depth adaptation in the host or surface runtime before rendering. Do not leak hidden values in labels, tooltips, or explanations.

Migration checklist

  • Inventory existing custom panels such as AgentFleetPanel and identify metrics, chips, status badges, actions, evidence blocks, and detail drawers.

  • Move collection shape into a DataViewSpec before changing UI code.

  • Replace inert user, customer, file, URL, and object fields with RichRef descriptors.

  • Use native-paired DataViewRenderer imports for React Native surfaces; keep web-only shell components out of native bundles.

  • Add tests for empty results, search/filter events, result count, row/card/detail equivalence, redaction, and action visibility.

Agent implementation prompt

Implement an entity workspace for <entity> using current ContractSpec packages.

Use DataViewSpec as the contract source. Prefer the native-paired EntityWorkspace facade for product-shell entity surfaces; use DataViewRenderer for renderer-specific examples and lower-level collection composition. Make row click, card click, and the explicit detail button call the same open-detail handler. Resolve edit/create through FeatureModuleSpec opToPresentation/forms first, then DataView source mutations or DataViewAction.operation, and use a host renderFormSlot fallback when no contract form is available. Render reference-like fields with RichRef, route panels through AdaptivePanel, seed view mode/density/data depth from @lssm-tech/lib.personalization, and apply RoleMorph/surface-runtime hidden field/action states before rendering. Verify web and native imports separately.