Knowledge example
Search content, read an article, navigate between results, and render a consumer-owned custom presentation.
The Knowledge example shows extension beyond tables and cards: the app registers its own request kind and article view. No core package is edited.
Run it#
- 1
Open the scenario
Open Knowledge in the playground. You should see searchable synthetic articles.
- 2
Run the scenario steps
Choose Search articles, Read article, then Security topic. You should see matched articles, a registered reading view, and the output of a custom request kind.
- 3
Inspect the custom request
After Security topic, choose Inspect. You should see the custom request (
demo.knowledge.by-topic) compile through the same validator as the built-in kinds. - 4
Run it locally
Choose More → Export project, unzip the download, then run
pnpm installandpnpm dev. You should see a local browse view and the statusrenderer-ready.
What it exercises#
- Search article titles, summaries, and content through a browse request.
- Render a registered custom view (
demo.knowledge-article) for reading. - Send a namespaced custom request that compiles into the normal pipeline.
- Keep the custom request and renderer bound to their registered contracts.
Make it yours#
- Swap the synthetic articles for your data adapter.
- Read permissions from your real app state.
- Register your own view or request kind — same contract, no core edits.
- 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.
{
"name": "aeliqo-knowledge-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"
}
}{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"lib": [
"ES2022",
"DOM"
],
"types": [
"vite/client"
],
"strict": true,
"noEmit": true
},
"include": [
"src/**/*.ts"
]
}<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Knowledge articles · Varendo</title></head><body><main><h1>Knowledge articles</h1><p id="status" role="status">Loading…</p><div id="app"></div></main><script type="module" src="/src/main.ts"></script></body></html>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: 'articles', revision: 'articles-1', label: 'Knowledge articles', identity: ['id'],
schema: z.object({id: z.string(), title: z.string(), topic: z.string(), excerpt: z.string()}),
fields: {title: {label: 'Title'}, topic: {label: 'Topic', role: 'dimension'}, excerpt: {label: 'Summary'}},
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: {articles: [
{
"id": "kb-1",
"title": "Rotate an API token safely",
"topic": "Security",
"excerpt": "Replace and revoke credentials safely."
},
{
"id": "kb-2",
"title": "Understand workspace roles",
"topic": "Access",
"excerpt": "Assign the smallest useful role."
}
]}},
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: 'articles-browse', kind: 'browse', resource: resource.id,
fields: ["title","topic","excerpt"],
}});
document.querySelector('#status')!.textContent = receipt.status;
window.addEventListener('pagehide', () => app.dispose(), {once: true});: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}# Knowledge articles · 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.