page.tsx166 lines · main
1import Link from 'next/link';
2
3import { DocsShell } from '../../components/shell';
4
5export const metadata = { title: 'ai schema generator' };
6
7export default function AiPage() {
8 return (
9 <DocsShell>
10 <h1 className="font-mono text-2xl tracking-tight">ai schema generator</h1>
11 <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]">
12 describe your app in plain english, get a draft <code>schema.ts</code> back. powered
13 by a self-hosted Qwen 2.5-coder 32B running on briven infrastructure — your prompt
14 never leaves briven&apos;s network.
15 </p>
16
17 <Section title="how to use it">
18 <ol className="list-decimal space-y-2 pl-5">
19 <li>
20 open the <em>ai schema</em> tab on any project at{' '}
21 <code>/dashboard/projects/&lt;p_id&gt;/ai-schema</code>
22 </li>
23 <li>type a description of your data model in the textarea (up to 4000 chars)</li>
24 <li>
25 click <strong>generate schema</strong>. expect 5-15 seconds for a typical
26 response — Qwen runs on a single DGX so larger prompts take longer
27 </li>
28 <li>
29 click <strong>copy</strong> on the result, paste into your project&apos;s{' '}
30 <code>briven/schema.ts</code>, and review every column before committing
31 </li>
32 <li>
33 run <code>briven deploy</code> as usual — the AI output goes through the same
34 schema-diff + migration path as a hand-written change
35 </li>
36 </ol>
37 </Section>
38
39 <Section title="what makes a good prompt">
40 <ul className="list-disc space-y-2 pl-5">
41 <li>
42 <strong>be specific about relationships</strong>: &quot;users have many posts, posts
43 have many comments, comments can reply to other comments&quot; ports cleanly. &quot;a blog&quot;
44 doesn&apos;t.
45 </li>
46 <li>
47 <strong>name your domain entities</strong>: &quot;projects, tasks, time-tracking
48 entries&quot; beats &quot;a productivity app&quot;
49 </li>
50 <li>
51 <strong>call out denormalised fields</strong>: &quot;each post stores its current
52 comment count alongside the comment rows&quot; saves a follow-up query
53 </li>
54 <li>
55 <strong>mention indexes you know you&apos;ll need</strong>: &quot;most queries are by
56 user_id and created_at descending&quot; signals the right index
57 </li>
58 </ul>
59 </Section>
60
61 <Section title="what the AI knows about briven">
62 <p>
63 the model is primed with a system prompt that:
64 </p>
65 <ul className="list-disc space-y-2 pl-5">
66 <li>
67 pins the available column helpers: <code>text()</code>, <code>bigint()</code>,{' '}
68 <code>boolean()</code>, <code>timestamp()</code>, <code>jsonb&lt;T&gt;()</code>,{' '}
69 <code>uuid()</code>
70 </li>
71 <li>
72 pins the modifiers: <code>.primaryKey()</code>, <code>.notNull()</code>,{' '}
73 <code>.default(...)</code>, <code>.nullable()</code>,{' '}
74 <code>.references(table, column)</code>, <code>.unique()</code>
75 </li>
76 <li>
77 insists on a primary-key column per table; prefers <code>text()</code> for
78 ULIDs; uses <code>bigint()</code> only for counters
79 </li>
80 <li>adds indexes only where a non-trivial query would scan — no over-indexing</li>
81 <li>
82 returns only the code (no markdown fences, no explanation) so it pastes cleanly
83 into your editor
84 </li>
85 </ul>
86 </Section>
87
88 <Section title="what it can't do">
89 <ul className="list-disc space-y-2 pl-5">
90 <li>
91 <strong>write your functions</strong> — schema only. function bodies are too app-
92 specific to template
93 </li>
94 <li>
95 <strong>guess your auth model</strong> — every table that needs per-user scoping
96 still needs an explicit <code>user_id</code> column and the function-level guard
97 </li>
98 <li>
99 <strong>refactor an existing schema</strong> — the prompt assumes you&apos;re
100 generating from scratch. for incremental changes, edit the schema by hand and let{' '}
101 <code>briven deploy</code> compute the diff
102 </li>
103 <li>
104 <strong>understand your data privacy constraints</strong> — review the output for
105 anything you wouldn&apos;t store; the AI doesn&apos;t know your jurisdiction
106 </li>
107 </ul>
108 </Section>
109
110 <Section title="privacy">
111 <p>
112 your prompt and the generated schema are <strong>not</strong> logged. only the
113 prompt length, response length, model name, and elapsed milliseconds are recorded
114 for operational monitoring. the request never leaves briven&apos;s infrastructure
115 — the Ollama instance runs on a dedicated DGX VPS in EU-Central.
116 </p>
117 <p>
118 we do not train or fine-tune the model on your prompts. there is no &quot;telemetry to
119 improve the service&quot; pipeline.
120 </p>
121 </Section>
122
123 <Section title="when it's offline">
124 <p>
125 if the dashboard shows &quot;AI assistant offline&quot;, the operator has not configured
126 the Ollama endpoint (BRIVEN_OLLAMA_URL is unset on the api container). this is the
127 default state on self-hosted briven — the feature is opt-in. self-hosters who want
128 it should:
129 </p>
130 <ol className="list-decimal space-y-2 pl-5">
131 <li>
132 run Ollama on a machine with at least 24GB GPU VRAM (qwen2.5-coder:32b
133 quantized fits in ~22GB)
134 </li>
135 <li>
136 <code>ollama pull qwen2.5-coder:32b</code>
137 </li>
138 <li>
139 set <code>BRIVEN_OLLAMA_URL=http://your-ollama-host:11434</code> on the api
140 container
141 </li>
142 <li>restart the api</li>
143 </ol>
144 </Section>
145
146 <p className="mt-12 font-mono text-xs text-[var(--color-text-subtle)]">
147 more AI features (function bodies, query suggestions, performance review) are{' '}
148 <Link href="/roadmap" className="underline hover:text-[var(--color-text)]">
149 on the roadmap
150 </Link>{' '}
151 for year-two.
152 </p>
153 </DocsShell>
154 );
155}
156
157function Section({ title, children }: { title: string; children: React.ReactNode }) {
158 return (
159 <section className="mt-10">
160 <h2 className="font-mono text-lg">{title}</h2>
161 <div className="mt-2 space-y-3 font-mono text-sm text-[var(--color-text-muted)]">
162 {children}
163 </div>
164 </section>
165 );
166}