page.tsx147 lines · main
| 1 | import { DocsShell } from '../../components/shell'; |
| 2 | |
| 3 | export const metadata = { title: 'cli templates' }; |
| 4 | |
| 5 | interface Template { |
| 6 | name: string; |
| 7 | pitch: string; |
| 8 | description: string; |
| 9 | schema: string; |
| 10 | highlights: readonly string[]; |
| 11 | } |
| 12 | |
| 13 | const TEMPLATES: readonly Template[] = [ |
| 14 | { |
| 15 | name: 'blank', |
| 16 | pitch: 'kick the tyres', |
| 17 | description: |
| 18 | 'one table (notes), one reactive query. the smallest valid briven project — useful when you just want to see the deploy / invoke loop work end-to-end before you commit to a real model.', |
| 19 | schema: `briven/ |
| 20 | ├── schema.ts # 1 table: notes |
| 21 | └── functions/ |
| 22 | └── listNotes.ts # 1 reactive query`, |
| 23 | highlights: ['1 table', '1 reactive query', '0 mutations'], |
| 24 | }, |
| 25 | { |
| 26 | name: 'todo-app', |
| 27 | pitch: 'canonical hello-world', |
| 28 | description: |
| 29 | 'classic todo list. 4 mutations covering create / toggle / rename / delete, 1 reactive query with a filter argument (open / done / all). matches the live demo at briven.tech/demo (when phase 4 lands).', |
| 30 | schema: `briven/ |
| 31 | ├── schema.ts # 1 table: todos |
| 32 | └── functions/ |
| 33 | ├── listTodos.ts # reactive query with ?filter=open|done|all |
| 34 | ├── createTodo.ts # mutation: validates body length, ulid id |
| 35 | ├── toggleTodo.ts # mutation: flips done + sets completedAt |
| 36 | ├── renameTodo.ts # mutation: body replace |
| 37 | └── deleteTodo.ts # mutation: hard delete by id`, |
| 38 | highlights: ['1 table', '1 query (with args)', '4 mutations', 'input validation'], |
| 39 | }, |
| 40 | { |
| 41 | name: 'chat', |
| 42 | pitch: 'real-time multi-room', |
| 43 | description: |
| 44 | 'rooms + messages with a per-room reactive query. shows how to use a foreign key + leading-column index to scope realtime fan-out to one room per subscriber. ulid ids, server-side timestamps.', |
| 45 | schema: `briven/ |
| 46 | ├── schema.ts # 2 tables: rooms, messages (FK) |
| 47 | └── functions/ |
| 48 | ├── listRooms.ts # reactive query |
| 49 | ├── createRoom.ts # mutation |
| 50 | ├── listMessages.ts # reactive query, args: { roomId } |
| 51 | └── postMessage.ts # mutation, args: { roomId, body }`, |
| 52 | highlights: ['2 tables with FK', 'per-room realtime', '2 queries', '2 mutations'], |
| 53 | }, |
| 54 | { |
| 55 | name: 'convex-notes', |
| 56 | pitch: 'familiar to convex users', |
| 57 | description: |
| 58 | 'multi-user notes with per-owner reactive listing + optional tag filter — mirrors the canonical convex notes-app shape. ownership is enforced inside each mutation as an explicit guard, not via row-level policy. comes pre-wired so a convex user sees their mental model land 1:1.', |
| 59 | schema: `briven/ |
| 60 | ├── schema.ts # 1 table: notes (owner-scoped) |
| 61 | └── functions/ |
| 62 | ├── listNotes.ts # reactive query, args: { ownerId, tag? } |
| 63 | ├── createNote.ts # mutation |
| 64 | ├── updateNote.ts # mutation with ownership guard |
| 65 | └── deleteNote.ts # mutation with ownership guard`, |
| 66 | highlights: ['multi-user', 'per-owner realtime', 'ownership guards', 'tag filter'], |
| 67 | }, |
| 68 | { |
| 69 | name: 'supabase-auth-todos', |
| 70 | pitch: 'familiar to supabase users', |
| 71 | description: |
| 72 | "auth-scoped todo list. every function reads ctx.session.userId and applies the same scoping supabase would do via row-level security — except the predicate lives in code, where you can read it and debug it. paste this to translate `auth.uid() = user_id` into briven's model.", |
| 73 | schema: `briven/ |
| 74 | ├── schema.ts # 1 table: todos (user_id-scoped) |
| 75 | └── functions/ |
| 76 | ├── myTodos.ts # reactive query, uses ctx.session.userId |
| 77 | ├── createTodo.ts # mutation, inserts with userId |
| 78 | ├── toggleTodo.ts # mutation with ownership guard |
| 79 | └── deleteTodo.ts # mutation with ownership guard`, |
| 80 | highlights: ['auth-aware', 'RLS → guards', '1 query', '3 mutations'], |
| 81 | }, |
| 82 | ]; |
| 83 | |
| 84 | export default function TemplatesPage() { |
| 85 | return ( |
| 86 | <DocsShell> |
| 87 | <h1 className="font-mono text-2xl tracking-tight">cli templates</h1> |
| 88 | <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]"> |
| 89 | optional starter files only — not the core product. the product path is{' '} |
| 90 | <code>briven setup</code> for a <strong>new</strong> cloud project, or{' '} |
| 91 | <code>briven connect p_…</code> for an <strong>existing</strong> one. pass{' '} |
| 92 | <code>--template</code> on setup when you want a sample schema/functions layout. |
| 93 | </p> |
| 94 | |
| 95 | <pre className="mt-4 overflow-x-auto rounded-md border border-[var(--color-border-subtle)] bg-[var(--color-code-bg)] p-3 font-mono text-xs text-[var(--color-code-text)]"> |
| 96 | <code>{`# new cloud project + sample files |
| 97 | briven setup --name my-app --template=todo-app |
| 98 | briven deploy |
| 99 | |
| 100 | # existing project — attach first, templates are optional later |
| 101 | briven connect p_… |
| 102 | # or local files only: briven init --template=todo-app`}</code> |
| 103 | </pre> |
| 104 | |
| 105 | <p className="mt-2 font-mono text-xs text-[var(--color-text-subtle)]"> |
| 106 | pass <code>briven init --list-templates</code> to print available names without |
| 107 | scaffolding. full connect flow:{' '} |
| 108 | <a className="underline" href="/connect"> |
| 109 | connect |
| 110 | </a> |
| 111 | . |
| 112 | </p> |
| 113 | |
| 114 | {TEMPLATES.map((t) => ( |
| 115 | <section |
| 116 | key={t.name} |
| 117 | id={t.name} |
| 118 | className="mt-10 scroll-mt-20 border-t border-[var(--color-border-subtle)] pt-8" |
| 119 | > |
| 120 | <div className="flex items-baseline justify-between gap-3"> |
| 121 | <h2 className="font-mono text-lg tracking-tight"> |
| 122 | <code>{t.name}</code> |
| 123 | </h2> |
| 124 | <span className="font-mono text-xs text-[var(--color-text-subtle)]">{t.pitch}</span> |
| 125 | </div> |
| 126 | <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]">{t.description}</p> |
| 127 | <ul className="mt-3 flex flex-wrap gap-2 font-mono text-[10px]"> |
| 128 | {t.highlights.map((h) => ( |
| 129 | <li |
| 130 | key={h} |
| 131 | className="rounded-md border border-[var(--color-border)] px-2 py-0.5 text-[var(--color-text-muted)]" |
| 132 | > |
| 133 | {h} |
| 134 | </li> |
| 135 | ))} |
| 136 | </ul> |
| 137 | <pre className="mt-4 overflow-x-auto rounded-md border border-[var(--color-border-subtle)] bg-[var(--color-code-bg)] p-3 font-mono text-xs text-[var(--color-code-text)]"> |
| 138 | <code>{t.schema}</code> |
| 139 | </pre> |
| 140 | <pre className="mt-3 overflow-x-auto rounded-md border border-[var(--color-border-subtle)] bg-[var(--color-code-bg)] p-3 font-mono text-xs text-[var(--color-code-text)]"> |
| 141 | <code>{`mkdir my-app && cd my-app\nbriven setup --name my-app --template=${t.name}\nbriven deploy`}</code> |
| 142 | </pre> |
| 143 | </section> |
| 144 | ))} |
| 145 | </DocsShell> |
| 146 | ); |
| 147 | } |