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.
DataViews Runtime Library
The
@lssm-tech/lib.contracts-spec/data-views
and@lssm-tech/lib.design-system
libraries provide the runtime logic and UI components to render DataViews in your application.Installation
bun add @lssm-tech/lib.contracts-spec @lssm-tech/lib.design-systemDataViewRenderer
The primary component for rendering any DataView. It automatically selects the correct layout (List, Table, Grid, Detail) based on the spec.
import { DataViewRenderer } from '@lssm-tech/lib.design-system';
import { MyUserList } from './specs/users.data-view';
export function UserPage() {
return (
<DataViewRenderer
spec={MyUserList}
items={users}
pagination={{ page: 1, pageSize: 20, total: 100 }}
onPageChange={(page) => fetchPage(page)}
/>
);
}Props
spec
: The DataViewSpec definition.items
: Array of data items to render.filters
: Current filter state object.onFilterChange
: Callback when typed filters change. Renderers emitDataViewFilterValue
objects for numeric, percent, currency, temporal, duration, and boolean filters.pagination
: Object withpage
,pageSize
,total
.onPageChange
: Callback when page changes.viewMode
/defaultViewMode
: Controlled or initial collection mode for specs that allowlist
,grid
, ortable
projections throughview.collection.viewModes
.density
/defaultDensity
: Controlled or initial density for collection renderers. Host apps can seed this from@lssm-tech/lib.personalization
while specs can declareview.collection.density
and tableview.density
defaults.dataDepth
/defaultDataDepth
: Controlled or initial summary/standard/detailed/exhaustive projection. Fields can declarevisibility.minDataDepth
, and collection specs can opt intoview.collection.personalization
persistence hints.
Collection Defaults And Data Depth
Use one authored
DataViewSpec
for list, grid, and table experiences.view.collection
declares allowed modes, toolbar controls, pagination defaults, density, data depth, and persistence hints.visibility.minDataDepth
lets a field appear only when the renderer is in a detailed or exhaustive mode.import { defineDataView } from '@lssm-tech/lib.contracts-spec/data-views';
export const AccountsDataView = defineDataView({
meta: {
key: 'crm.accounts',
version: '1.0.0',
title: 'Accounts',
description: 'Customer account workspace',
domain: 'crm',
entity: 'account',
owners: ['@crm'],
tags: ['crm', 'accounts'],
stability: 'stable',
},
source: {
primary: { key: 'crm.accounts.list', version: '1.0.0' },
},
view: {
kind: 'table',
fields: [
{ key: 'name', label: 'Name', dataPath: 'name', sortable: true },
{ key: 'owner', label: 'Owner', dataPath: 'owner' },
{ key: 'arr', label: 'ARR', dataPath: 'arr', format: { type: 'currency', currency: 'EUR' } },
{
key: 'internalNotes',
label: 'Internal notes',
dataPath: 'internalNotes',
visibility: { minDataDepth: 'detailed' },
},
],
columns: [
{ field: 'name' },
{ field: 'owner' },
{ field: 'arr' },
{ field: 'internalNotes' },
],
collection: {
viewModes: {
defaultMode: 'table',
allowedModes: ['list', 'grid', 'table'],
},
pagination: {
pageSize: 25,
pageSizeOptions: [10, 25, 50],
},
toolbar: {
search: true,
viewMode: true,
filters: true,
density: true,
dataDepth: true,
},
density: 'comfortable',
dataDepth: 'standard',
personalization: {
enabled: true,
persist: {
viewMode: true,
density: true,
dataDepth: true,
pageSize: true,
},
},
},
},
});Personalization Bridge
Resolve user preferences in the host app, then pass ordinary renderer props into
DataViewRenderer
. The bridge helper lives in@lssm-tech/lib.personalization
, so the design-system renderer stays portable for apps that do not use personalization. See thepersonalization library guide
for the behavior tracker, analyzer, and DataView preference resolver.import { DataViewRenderer } from '@lssm-tech/lib.design-system';
import { resolveDataViewPreferences } from '@lssm-tech/lib.personalization/data-view-preferences';
const resolved = resolveDataViewPreferences({
spec: AccountsDataView,
preferences: profile.canonical,
insights,
record: savedDataViewPreference,
});
<DataViewRenderer
spec={AccountsDataView}
items={accounts}
defaultViewMode={resolved.viewMode}
defaultDensity={resolved.density}
defaultDataDepth={resolved.dataDepth}
pagination={{
page,
pageSize: resolved.pageSize ?? 25,
total,
}}
onViewModeChange={(viewMode) => {
tracker.trackDataViewInteraction({
dataViewKey: AccountsDataView.meta.key,
dataViewVersion: AccountsDataView.meta.version,
action: 'view_mode_changed',
viewMode,
});
}}
onDensityChange={(density) => {
tracker.trackDataViewInteraction({
dataViewKey: AccountsDataView.meta.key,
action: 'density_changed',
density,
});
}}
onDataDepthChange={(dataDepth) => {
tracker.trackDataViewInteraction({
dataViewKey: AccountsDataView.meta.key,
action: 'data_depth_changed',
dataDepth,
});
}}
/>;
Agent Prompt
Use this prompt when asking an implementation agent to add a preference-aware collection DataView without breaking package boundaries.
Implement a production DataView for <entity>.
Requirements:
- Define one canonical DataViewSpec with kind 'table', collection viewModes for list/grid/table, pagination defaults, toolbar search/filter/view mode/density/dataDepth controls, and personalization persist hints.
- Mark fields that should only appear in richer experiences with visibility.minDataDepth.
- Render it with DataViewRenderer using plain props from resolveDataViewPreferences.
- Track user interactions with trackDataViewInteraction for view mode, density, data depth, search, filters, sorting, and pagination.
- Keep @lssm-tech/lib.design-system independent from @lssm-tech/lib.personalization.
- Add focused tests for default resolution, invalid-mode fallback, data-depth projection, and behavior-derived preferred view mode.Query Generation
The
DataViewQueryGenerator
utility helps translate DataView parameters (filters, sorting, pagination) into query arguments for your backend.import { DataViewQueryGenerator } from '@lssm-tech/lib.contracts-spec/data-views/query-generator';
const generator = new DataViewQueryGenerator(MyUserList);
const params = {
pagination: { page: 1, pageSize: 20 },
filters: {
role: { kind: 'single', value: 'admin' },
revenue: { kind: 'range', from: 1000, to: 5000 },
lastSeenAt: { kind: 'single', value: '2026-04-28T08:30:00Z' }
}
};
const errors = generator.validateParams(params);
const query = generator.generate(params);
// query.input contains skip/take plus the typed filter payloads.Libraries overview
Navigate the core libraries, runtimes, and system packages that make up the open foundation.
Personalization
Track behavior events, resolve DataView preferences, and convert insights into overlays or workflow adaptations.
Why ContractSpec
Keep educational and comparison content reachable without letting it define the primary OSS learning path.