Varendo

Support example

Search tickets, inspect details, edit a draft, and move status through a confirmed application action.

The Support example shows business UI: ticket text is untrusted input, but it cannot grant permissions, install code, or trigger a write.

Run it

  1. 1

    Open the scenario

    Open Support in the playground. You should see a ticket table.

  2. 2

    Run the scenario steps

    Choose Search tickets, Browse open, Open ticket, then Edit ticket. You should see filtered results, a detail view, and a form holding the ticket's current values.

  3. 3

    Watch the confirmation

    Submit a change. You should see a review dialog first — the runtime validates the proposal, but confirming stays your decision.

  4. 4

    Inspect the run

    Choose Inspect. You should see the request, result, view policy, and any diagnostics.

  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

  • Search permitted tickets through the bounded query contract.
  • Open ticket detail by its stable ticket identity.
  • Edit a draft with validation; dirty fields survive layout changes.
  • Preview an action, require your confirmation, then execute once.
  • Report action receipts through the host; retry or reconcile failed writes according to their outcome.

Make it yours

  • Swap the synthetic tickets for your data adapter.
  • Read permissions from your real app state.
  • Route writes through your registered action with fresh authorization.
  • 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-support-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>Support tickets · Varendo</title></head><body><main><h1>Support tickets</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: 'tickets', revision: 'tickets-1', label: 'Support tickets', identity: ['id'],
  schema: z.object({id: z.string(), subject: z.string(), customer: z.string(), status: z.string(), priority: z.string()}),
  fields: {subject: {label: 'Subject'}, customer: {label: 'Customer'}, status: {label: 'Status', role: 'dimension'}, priority: {label: 'Priority'}},
  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: {tickets: [
  {
    "id": "t-1",
    "subject": "Invoice PDF unavailable",
    "customer": "Northstar",
    "status": "Open",
    "priority": "High"
  },
  {
    "id": "t-2",
    "subject": "Rotate API token",
    "customer": "Kite Labs",
    "status": "Resolved",
    "priority": "Low"
  }
]}},
  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: 'tickets-browse', kind: 'browse', resource: resource.id,
  fields: ["subject","customer","status","priority"],
}});
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
# Support tickets · 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.