Varendo

People example

Browse, filter, detail, and trend over a registered People resource with correct temporal meaning.

The People example shows the classic table-to-cards adaptation on a small employee list — plus a detail view and a monthly headcount chart. No AI involved.

Run it

  1. 1

    Open the scenario

    Open People in the playground. You should see a table of synthetic employees.

  2. 2

    Run the scenario steps

    Choose Engineering only, Open Ada, then Monthly headcount. You should see a filtered table, a detail view, and a month-end trend chart.

  3. 3

    Inspect the run

    Choose Inspect. You should see the validated request, the result, and the reason that view was picked.

  4. 4

    Shrink the region

    Make the region narrower. You should see the table swap to cards with the same rows and filter.

  5. 5

    Run it locally

    Choose More → Export project, unzip the download, then run pnpm install and pnpm dev. You should see a local browse view and the status renderer-ready.

What it exercises

  • Browse a typed collection with stable identity per row.
  • Filter by team while keeping stable identity on the returned rows.
  • Open one person in detail, including on a narrow layout.
  • Chart a registered month-end measure by month.
  • Reject an unknown field, invalid aggregate, or unregistered view.

Make it yours

  • Swap the synthetic rows for your data adapter.
  • Read permissions from your real app state.
  • Keep each row's identity stable and its meaning explicit.
  • Dispose the app when the host removes the surface.

When it fails

An unknown field or view returns a diagnostic and keeps the last permitted view. A denied permission read returns no data. Fix the contract or the trusted policy, then send the request again.

Local browse starter source

The exported project renders one browse view. The additional Playground steps above require their resource meanings, forms/actions, or custom registrations; they are not bundled in this minimal starter. Follow Connect your data to add those contracts.

package.json · compiled export source
{
  "name": "aeliqo-people-example",
  "private": true,
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc --noEmit && vite build"
  },
  "dependencies": {
    "@varendo/core": "0.1.0",
    "@varendo/runtime": "0.1.0",
    "@varendo/web": "0.1.0",
    "zod": "4.5.4"
  },
  "devDependencies": {
    "typescript": "7.0.2",
    "vite": "8.2.2"
  }
}
tsconfig.json · compiled export source
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "lib": [
      "ES2022",
      "DOM"
    ],
    "types": [
      "vite/client"
    ],
    "strict": true,
    "noEmit": true
  },
  "include": [
    "src/**/*.ts"
  ]
}
index.html · compiled export source
<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>People · Varendo</title></head><body><main><h1>People</h1><p id="status" role="status">Loading…</p><div id="app"></div></main><script type="module" src="/src/main.ts"></script></body></html>
src/main.ts · compiled export source
import {defineResource} from '@varendo/core';
import {createQueryFunctionRegistry} from '@varendo/core/expressions';
import {createLocalDataService} from '@varendo/runtime/data';
import {createAeliqoApp} from '@varendo/web/app';
import {z} from 'zod';
import './style.css';

const resource = defineResource({
  id: 'people', revision: 'people-1', label: 'People', identity: ['id'],
  schema: z.object({id: z.string(), name: z.string(), team: z.string(), location: z.string()}),
  fields: {name: {label: 'Name'}, team: {label: 'Team', role: 'dimension'}, location: {label: 'Location'}},
  presentation: {allowedViews: ["table","cards"]},
});

const functions = createQueryFunctionRegistry({version: '2'});
if (!functions.ok) throw new Error(functions.diagnostics[0].message);
const data = createLocalDataService({
  snapshot: {catalog: resource.catalog, sourceRevision: 'synthetic-1', records: {people: [
  {
    "id": "p-1",
    "name": "Ada Chen",
    "team": "Design",
    "location": "Jakarta"
  },
  {
    "id": "p-2",
    "name": "Sam Rivera",
    "team": "Engineering",
    "location": "Lisbon"
  }
]}},
  functionRegistry: functions.value,
  sourceLimits: {rows: 1_000, bytes: 1_000_000},
  authorize: () => ({ok: true, value: {scopeDigest: 'local-demo', policyRevision: 'policy-1'}}),
});

const app = createAeliqoApp({
  resources: [{resource, data}],
  authority: {read: () => ({ok: true, value: {
    principalKey: 'local-user', scopeDigest: 'local-demo', policyRevision: 'policy-1',
    experienceRevision: 'web-1', grants: ['task.evaluate', 'result.inspect', 'experience.commit'],
    readContext: {principal: 'local-user'},
  }})},
});

const target = document.querySelector<HTMLElement>('#app');
if (target === null) throw new Error('The app target is missing.');
const mounted = app.mount({target, regionId: 'main', resourceId: resource.id});
if (!mounted.ok) throw new Error(mounted.diagnostics[0].message);
const receipt = await app.render({regionId: 'main', intent: {
  version: '1', id: 'people-browse', kind: 'browse', resource: resource.id,
  fields: ["name","team","location"],
}});
document.querySelector('#status')!.textContent = receipt.status;
window.addEventListener('pagehide', () => app.dispose(), {once: true});
src/style.css · compiled export source
:root{font-family:Inter,ui-sans-serif,system-ui;color:#202033;background:#f7f7fb}body{margin:0}main{inline-size:min(72rem,calc(100% - 2rem));margin:3rem auto}#app{container-type:inline-size;min-block-size:20rem}
README.md · compiled export source
# People · Varendo 0.1.0

Synthetic source project exported from the Varendo playground. Install requires the pinned 0.1.0 packages to be published to npm.

```sh
pnpm install
pnpm dev
```

The application works without an AI provider. Replace the local snapshot and authority adapter with application-owned implementations before using real data.