docs-corpus.ts551 lines · main
1/**
2 * Hand-curated corpus index of every docs page. Used by the docs search
3 * endpoint (and tomorrow by the AI docs assistant — the search picks the
4 * top N pages by word-overlap, the assistant forwards them to Ollama).
5 *
6 * Each entry is one page. `summary` is what the page documents in 1-2
7 * sentences — written as if you were describing the page to someone
8 * trying to find the right one. Keywords matter; this is what the
9 * search scores against.
10 *
11 * When you add a docs page, add an entry here. The pages list is short
12 * (~25) so a hand-curated index reads faster than an automated one,
13 * and the search results carry the editorial framing that the model
14 * inherits when it builds its answer.
15 */
16
17export interface DocsCorpusEntry {
18 readonly slug: string;
19 readonly title: string;
20 readonly summary: string;
21 readonly keywords: readonly string[];
22}
23
24export const DOCS_CORPUS: readonly DocsCorpusEntry[] = [
25 {
26 slug: '/',
27 title: 'briven docs · overview',
28 summary:
29 'landing page for briven docs. Doltgres-first (Postgres wire + version history for control and project DBs), MinIO S3 for files, Auth, MCP. who it is for (typescript developers), where to start: setup (new) or connect (existing).',
30 keywords: [
31 'overview',
32 'introduction',
33 'getting started',
34 'about',
35 'what is briven',
36 'doltgres',
37 'minio',
38 's3',
39 ],
40 },
41 {
42 slug: '/undo',
43 title: 'undo + snapshots · version history (doltgres / git-for-data)',
44 summary:
45 'briven runs on doltgres (postgres-wire git-for-data). plain-language undo and snapshots for non-coders, plus the developer SQL behind it: dolt_log, DOLT_HASHOF, DOLT_COMMIT, DOLT_TAG, dolt_tags, dolt_diff, dolt_diff_summary, DOLT_RESET, DOLT_BRANCH / DOLT_CHECKOUT / DOLT_MERGE. explains the dolt vs doltgres vs doltlab ecosystem and which one briven actually uses.',
46 keywords: [
47 'undo',
48 'snapshot',
49 'snapshots',
50 'version history',
51 'rollback',
52 'restore',
53 'time travel',
54 'doltgres',
55 'dolt',
56 'doltlab',
57 'git for data',
58 'branch',
59 'diff',
60 'commit',
61 'backup',
62 ],
63 },
64 {
65 slug: '/quickstart',
66 title: 'quickstart · five minutes from clone to first invoke',
67 summary:
68 'start: briven setup --name (NEW project) or briven connect p_… (EXISTING), edit schema/functions, deploy, invoke. never setup --project. templates optional. dashboard-only studio path also covered.',
69 keywords: [
70 'install',
71 'setup',
72 'briven setup',
73 'briven connect',
74 'init',
75 'first',
76 'cli install',
77 'getting started',
78 'tutorial',
79 'first deploy',
80 'convex',
81 ],
82 },
83 {
84 slug: '/connect',
85 title: 'connect · shell setup, sdk, and mcp',
86 summary:
87 'how to connect to briven. briven setup = create a NEW cloud project + wire folder. briven connect = attach an EXISTING project (p_…). path a: @briven/client sdk. path b: mcp for ai agents. platform is Doltgres-first; files use MinIO S3. documents platform session vs project keys.',
88 keywords: [
89 'connect',
90 'briven setup',
91 'briven connect',
92 'setup',
93 'login',
94 'oauth',
95 'cli auth',
96 'sdk',
97 'mcp',
98 'api key',
99 'brk_',
100 'wire folder',
101 'new project',
102 'existing project',
103 'doltgres',
104 's3',
105 'minio',
106 ],
107 },
108 {
109 slug: '/cli',
110 title: 'cli reference',
111 summary:
112 'every briven cli command — setup (new project only), connect (existing project), projects, init, login, link, deploy, dev, logs, db shell, env, invoke, export, import, doctor, whoami, auth scaffold, storage. one section per command with usage and flags.',
113 keywords: [
114 'cli',
115 'briven setup',
116 'briven init',
117 'briven deploy',
118 'briven dev',
119 'briven logs',
120 'briven login',
121 'briven connect',
122 'briven auth',
123 'briven storage',
124 'commands',
125 'terminal',
126 ],
127 },
128 {
129 slug: '/schema',
130 title: 'schema dsl reference',
131 summary:
132 'briven schema column helpers (text, bigint, boolean, timestamp, jsonb, uuid), modifiers (.primaryKey, .notNull, .references, .default, .unique, .nullable), index declarations, and the schema diff semantics that drive transactional migrations.',
133 keywords: [
134 'schema',
135 'columns',
136 'types',
137 'tables',
138 'migrations',
139 'references',
140 'foreign key',
141 'index',
142 'primary key',
143 'dsl',
144 ],
145 },
146 {
147 slug: '/functions',
148 title: 'functions reference',
149 summary:
150 'briven function wrappers — query() (reactive reads), mutation() (transactional writes), action() (long-running or external side effects). covers Ctx, db builder chains, brivenError, the lifecycle of a function call, and common patterns (validation, pagination, rate-limited writes).',
151 keywords: [
152 'functions',
153 'query',
154 'mutation',
155 'action',
156 'ctx',
157 'ctx.db',
158 'brivenError',
159 'validation',
160 'reactive',
161 'transaction',
162 ],
163 },
164 {
165 slug: '/realtime',
166 title: 'realtime — reactive queries',
167 summary:
168 'how reactive subscriptions work end-to-end: useQuery in the client, the realtime websocket service, postgres LISTEN/NOTIFY triggers auto-generated from the schema, and the re-invoke + push pipeline. covers connection limits, reconnection behaviour, and what makes a query reactive vs static.',
169 keywords: [
170 'realtime',
171 'reactive',
172 'websocket',
173 'useQuery',
174 'subscribe',
175 'listen',
176 'notify',
177 'live',
178 'updates',
179 'subscriptions',
180 ],
181 },
182 {
183 slug: '/sdks',
184 title: 'sdk reference — react, svelte, vue, vanilla',
185 summary:
186 '@briven/client (framework-agnostic), @briven/react (useQuery, useMutation hooks), @briven/svelte (stores), @briven/vue (composables). reconnect/backoff behaviour, ssr considerations, and how token auth flows from the dashboard to the SDK.',
187 keywords: [
188 'sdk',
189 'client',
190 'react',
191 'svelte',
192 'vue',
193 'useQuery',
194 'useMutation',
195 'hooks',
196 'composables',
197 'stores',
198 ],
199 },
200 {
201 slug: '/api',
202 title: 'http api reference',
203 summary:
204 'every public endpoint grouped by area: invoke, realtime, projects, deployments, studio, logs + stats, usage, api keys, project members, orgs, billing. method, path, auth, and a one-line summary each.',
205 keywords: [
206 'api',
207 'http',
208 'rest',
209 'endpoints',
210 'routes',
211 'invoke',
212 'deployments',
213 'projects api',
214 ],
215 },
216 {
217 slug: '/self-host',
218 title: 'self-host',
219 summary:
220 'run briven on your own infrastructure. four services (api, runtime, realtime, web) + Doltgres SQL engine + redis + minio behind traefik. dokploy template, coolify template, plain docker compose. env vars, observability, licensing. hosted briven.tech is Doltgres-first.',
221 keywords: [
222 'self-host',
223 'self host',
224 'docker',
225 'docker compose',
226 'dokploy',
227 'coolify',
228 'deploy',
229 'infrastructure',
230 'on-premise',
231 'doltgres',
232 ],
233 },
234 {
235 slug: '/ai',
236 title: 'ai features',
237 summary:
238 'briven ai surface: ai schema generator (NL prompt → draft schema.ts), ai function generator (NL + schema context → draft function file), ai explain code (snippet → plain-english walkthrough). all run on a self-hosted Qwen 2.5-coder model; prompts and outputs are not logged.',
239 keywords: [
240 'ai',
241 'ollama',
242 'qwen',
243 'schema generator',
244 'function generator',
245 'explain code',
246 'llm',
247 'natural language',
248 ],
249 },
250 {
251 slug: '/examples',
252 title: 'examples gallery',
253 summary:
254 'small end-to-end briven projects (realtime-chat, counter, …) with their full schema + functions + client wiring. each example is also available as a template via `briven init --template <name>`.',
255 keywords: ['examples', 'samples', 'demo', 'realtime chat', 'counter', 'starter'],
256 },
257 {
258 slug: '/templates',
259 title: 'project templates',
260 summary:
261 'optional starter templates via `briven setup --template` or `briven init --template`. not the core product — only sample files. new projects: briven setup; existing: briven connect.',
262 keywords: [
263 'templates',
264 'starter',
265 'briven setup',
266 'briven init',
267 'scaffold',
268 'boilerplate',
269 ],
270 },
271 {
272 slug: '/migration',
273 title: 'migration overview',
274 summary:
275 'how to migrate to briven from another backend. five principles (read before write, parallel-run, back up twice, schema-first, one product at a time), the ten-step playbook, and per-source guides (convex, supabase, postgres, drizzle, prisma, firebase, hasura, nextauth, mongodb).',
276 keywords: [
277 'migration',
278 'migrate',
279 'move',
280 'switch',
281 'convex',
282 'supabase',
283 'firebase',
284 'postgres',
285 'mongo',
286 ],
287 },
288 {
289 slug: '/migration/convex',
290 title: 'migration · convex → briven',
291 summary:
292 'port a convex project: union-of-literal fields → text() with app-level validation; v.id() → text().references(); _creationTime → explicit created_at column; convex auth → better-auth.',
293 keywords: ['convex', 'v.id', 'defineTable', 'union literal', 'migration from convex'],
294 },
295 {
296 slug: '/migration/supabase',
297 title: 'migration · supabase → briven',
298 summary:
299 'port a supabase project: schema 1:1 (both postgres), row-level-security policies → app-level guards in function code, edge functions → briven functions, storage → minio, auth → better-auth.',
300 keywords: ['supabase', 'rls', 'edge functions', 'supabase storage', 'supabase auth'],
301 },
302 {
303 slug: '/migration/postgres',
304 title: 'migration · raw postgres → briven',
305 summary:
306 'the straightest path. schema.sql → briven/schema.ts via the dsl, pg_dump | pg_restore against the briven dsn, port handlers into briven/functions/.',
307 keywords: ['postgres', 'raw postgres', 'sql', 'pg_dump', 'pg_restore', 'plain postgres'],
308 },
309 {
310 slug: '/migration/drizzle',
311 title: 'migration · drizzle → briven',
312 summary:
313 "drizzle schema ports almost 1:1; integer → bigint; .defaultNow() → .default('now()'); .references(() => …) → .references('table', 'column'); db.select chains become ctx.db chains.",
314 keywords: ['drizzle', 'drizzle-orm', 'pgTable'],
315 },
316 {
317 slug: '/migration/prisma',
318 title: 'migration · prisma → briven',
319 summary:
320 'prisma dsl → briven dsl: @id/cuid/uuid → ulid in function code; Int → bigint; Json? → jsonb<T>().nullable(); enums as application-side validation; PrismaClient calls → ctx.db builder chains.',
321 keywords: ['prisma', 'PrismaClient', 'schema.prisma', 'prisma migrate'],
322 },
323 {
324 slug: '/migration/firebase',
325 title: 'migration · firebase / firestore → briven',
326 summary:
327 'hardest path. document model → relational model is a manual remap. plan for an extended parallel-run window (2+ weeks) to catch shape mismatches.',
328 keywords: ['firebase', 'firestore', 'document database', 'nosql'],
329 },
330 {
331 slug: '/migration/mongodb',
332 title: 'migration · mongodb → briven',
333 summary:
334 'collection → table with deliberate jsonb vs flatten decisions per embedded doc; ObjectId → text + ulid for new ids; mongoexport → custom transform → COPY for the data move.',
335 keywords: ['mongodb', 'mongo', 'mongoose', 'ObjectId', 'jsonb', 'collection', 'document store'],
336 },
337 {
338 slug: '/migration/hasura',
339 title: 'migration · hasura → briven',
340 summary:
341 'postgres half ports for free; the work is the permissions port — every (role, table, action) triple from hasura metadata becomes a guard in function code.',
342 keywords: ['hasura', 'graphql', 'permissions', 'role-based access'],
343 },
344 {
345 slug: '/migration/nextauth',
346 title: 'migration · nextauth / auth.js → briven',
347 summary:
348 'schema maps 1:1 (both target better-auth shape); provider port is trivial; the work is replacing getServerSession + useSession callsites and choosing preserve-ids vs preserve-sessions cutover.',
349 keywords: ['nextauth', 'auth.js', 'getServerSession', 'useSession', 'better-auth'],
350 },
351 {
352 slug: '/operator',
353 title: 'operator guide',
354 summary:
355 'operating a briven deployment: Doltgres-first SQL, MinIO file storage vs platform DR vault, env vars, restore drills, alerting, observability (grafana + loki + prometheus + alertmanager), upgrade procedures.',
356 keywords: [
357 'operator',
358 'ops',
359 'doltgres',
360 'backup',
361 'restore',
362 'observability',
363 'grafana',
364 'loki',
365 'prometheus',
366 'backups',
367 'restore',
368 'alerts',
369 ],
370 },
371 {
372 slug: '/roadmap',
373 title: 'roadmap',
374 summary:
375 'what is in briven today, what is queued for the next phase, what is deliberately out of scope for year one (light mode, mobile apps, graphql).',
376 keywords: ['roadmap', 'plans', 'coming soon', 'phase 3', 'phase 4'],
377 },
378 {
379 slug: '/support',
380 title: 'support',
381 summary:
382 'where to ask for help, what to include in an issue, what NOT to paste (secrets, full session cookies, real user emails). private discord for beta users.',
383 keywords: ['support', 'help', 'discord', 'community', 'contact'],
384 },
385 {
386 slug: '/status',
387 title: 'status',
388 summary:
389 'live health of api.briven.tech, realtime.briven.tech, runtime.briven.tech, and briven.tech itself. probes /health + /ready on each. red/green per service with latency + http status.',
390 keywords: ['status', 'uptime', 'health', 'outage', 'incident', 'live'],
391 },
392 {
393 slug: '/vector-search',
394 title: 'vector search · embeddings + intended shapes',
395 summary:
396 'intended vector search shapes. product engine is Doltgres — stock Postgres pgvector is NOT assumed available; check /doltgres/limitations. store embeddings as app-managed payloads or use an external ANN service while source-of-truth rows stay on briven.',
397 keywords: [
398 'vector',
399 'pgvector',
400 'embeddings',
401 'semantic search',
402 'nearest neighbor',
403 'similarity',
404 'hnsw',
405 'cosine',
406 'nomic',
407 'doltgres',
408 'limitations',
409 ],
410 },
411 {
412 slug: '/ask',
413 title: 'ask the docs · AI assistant',
414 summary:
415 'natural-language search across the docs corpus. retrieves the top 3 matching pages, answers your question grounded in those pages, cites the slugs. powered by the same self-hosted Qwen 2.5-coder backend as the dashboard ai surfaces.',
416 keywords: ['ask', 'ai assistant', 'chat', 'question', 'help', 'search ai'],
417 },
418 {
419 slug: '/changelog',
420 title: 'changelog',
421 summary:
422 'reverse-chronological list of every notable change to briven, tagged by feat / fix / security / docs / infra / chore. also available as RSS at /changelog/feed.xml.',
423 keywords: ['changelog', 'releases', 'updates', 'history', 'whats new'],
424 },
425 {
426 slug: '/storage',
427 title: 'storage · per-project MinIO S3 buckets',
428 summary:
429 'project file storage on MinIO at s3.briven.tech (proj-… buckets, brvn access keys). not the SQL database (Doltgres) and not platform DR backups. dashboard mint key, CLI setup/connect write env, MCP storage_* tools including soft-delete restore, public media.briven.tech URLs.',
430 keywords: [
431 'storage',
432 's3',
433 'minio',
434 'bucket',
435 'upload',
436 'download',
437 'presigned',
438 'files',
439 'media',
440 'brvn',
441 'restore',
442 'soft delete',
443 ],
444 },
445 {
446 slug: '/doltgres',
447 title: 'doltgres · the sql engine (control + every project)',
448 summary:
449 'briven is Doltgres-first: Postgres wire + git-for-data for the platform control database and every project database. not MySQL Dolt. not stock Postgres as the product engine. links to install, types, version-control, limitations.',
450 keywords: [
451 'doltgres',
452 'doltgresql',
453 'database',
454 'postgres',
455 'git for data',
456 'engine',
457 'version control',
458 'sql',
459 ],
460 },
461 {
462 slug: '/auth',
463 title:
464 'auth · @briven/auth sign-in, 2FA backup codes, testing tokens, sender domain, jwt+jwks',
465 summary:
466 'drop-in end-user sign-in on Doltgres control plane: email + password, magic link, OTP, passkeys, OAuth. wire with briven setup (new) or briven connect (existing) then briven auth scaffold. pk_briven_auth keys only in browser. React/Vue/Svelte hooks, BrivenSignIn, 2FA, testing tokens, sender domain DNS, JWT+JWKS.',
467 keywords: [
468 'auth',
469 'sign in',
470 'login',
471 'magic link',
472 'otp',
473 'passkey',
474 'oauth',
475 'two-factor',
476 '2fa',
477 'mfa',
478 'backup codes',
479 'recovery codes',
480 'testing tokens',
481 'e2e',
482 'test token',
483 'password policy',
484 'scaffold',
485 'sender domain',
486 'email domain',
487 'custom domain email',
488 'noreply',
489 'spf',
490 'dkim',
491 'dns records',
492 'email not arriving',
493 'branding',
494 'from address',
495 'fallback sender',
496 'jwt',
497 'jwks',
498 'token',
499 'verifiable token',
500 'verify session locally',
501 'token endpoint',
502 'json web key set',
503 'key rotation',
504 'new device',
505 'rate limit',
506 ],
507 },
508];
509
510/**
511 * Score one corpus entry against a query. Returns a number in [0, ∞);
512 * 0 means no match. Higher = better. Algorithm: token overlap between
513 * query and (title + summary + keywords), weighted by where the hit
514 * lands — keyword hits score double, title hits triple.
515 *
516 * Tokenisation: lowercase, split on non-letter-digit. So "briven init"
517 * and "briven-init" tokenise to ['briven', 'init'] and match the same
518 * entries.
519 */
520export function scoreEntry(entry: DocsCorpusEntry, query: string): number {
521 const tokens = tokenise(query);
522 if (tokens.length === 0) return 0;
523 const titleTokens = new Set(tokenise(entry.title));
524 const summaryTokens = new Set(tokenise(entry.summary));
525 const keywordTokens = new Set(entry.keywords.flatMap((k) => tokenise(k)));
526 let score = 0;
527 for (const t of tokens) {
528 if (titleTokens.has(t)) score += 3;
529 if (keywordTokens.has(t)) score += 2;
530 if (summaryTokens.has(t)) score += 1;
531 }
532 return score;
533}
534
535export function tokenise(text: string): string[] {
536 return text
537 .toLowerCase()
538 .split(/[^a-z0-9]+/)
539 .filter((t) => t.length > 1);
540}
541
542/**
543 * Top-N matches for a query. Stable sort: higher score first, then
544 * shorter slug (so '/cli' beats '/cli/some-deep-page' on a tie).
545 */
546export function searchDocs(query: string, limit = 5): readonly DocsCorpusEntry[] {
547 const scored = DOCS_CORPUS.map((e) => ({ entry: e, score: scoreEntry(e, query) }))
548 .filter((s) => s.score > 0)
549 .sort((a, b) => b.score - a.score || a.entry.slug.length - b.entry.slug.length);
550 return scored.slice(0, limit).map((s) => s.entry);
551}