page.tsx405 lines · main
| 1 | import { PmTabs } from '../../components/pm-tabs'; |
| 2 | import { DocsShell } from '../../components/shell'; |
| 3 | import { pmDlx, pmExec, pmInstall } from '../../lib/pm'; |
| 4 | |
| 5 | export const metadata = { |
| 6 | title: 'connect', |
| 7 | }; |
| 8 | |
| 9 | const INSTALL_CLIENT = pmInstall('@briven/client'); |
| 10 | const ONE_SHOT = pmDlx('briven'); |
| 11 | const SETUP = pmExec( |
| 12 | 'briven setup', |
| 13 | 'briven setup --name my-app', |
| 14 | 'briven setup my-app', |
| 15 | 'briven setup --name my-app --template todo-app --region eu-west', |
| 16 | ); |
| 17 | const SETUP_THEN = pmExec('briven deploy', 'briven dev'); |
| 18 | const CONNECT = pmExec( |
| 19 | 'briven connect', |
| 20 | 'briven connect p_01HZ...', |
| 21 | 'briven connect --project p_01HZ...', |
| 22 | ); |
| 23 | const CONNECT_STATUS = pmExec('briven connect status'); |
| 24 | const PROJECTS_REMOTE = pmExec('briven projects list --remote'); |
| 25 | const PROJECTS_CREATE = pmExec( |
| 26 | 'briven projects create --name my-app', |
| 27 | 'briven projects create --name my-app --region eu-west', |
| 28 | ); |
| 29 | const PROJECTS_USE = pmExec( |
| 30 | 'briven projects use p_01HZ...', |
| 31 | 'briven projects use p_01HZ... --link', |
| 32 | ); |
| 33 | const PROJECTS_UNLINK = pmExec('briven projects unlink p_01HZ...'); |
| 34 | const INIT_LINK = pmExec('briven init', 'briven link --project p_01HZ...', 'briven deploy'); |
| 35 | const LIFECYCLE = pmExec( |
| 36 | 'briven setup my-app # new project', |
| 37 | 'briven connect p_… # OR existing', |
| 38 | 'briven deploy', |
| 39 | ); |
| 40 | |
| 41 | export default function ConnectPage() { |
| 42 | return ( |
| 43 | <DocsShell> |
| 44 | <h1 className="font-mono text-2xl tracking-tight">connect</h1> |
| 45 | <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]"> |
| 46 | how to connect to briven. <strong className="text-[var(--color-text)]">shell first:</strong>{' '} |
| 47 | <code>briven setup</code> = brand-new project · <code>briven connect</code> = existing |
| 48 | project. both sign you in, mint project S3 keys when possible, and wire this folder. then |
| 49 | SDK / HTTP / Auth / MCP. |
| 50 | </p> |
| 51 | |
| 52 | <div className="mt-6 rounded-md border border-[var(--color-border-subtle)] bg-[var(--color-surface)] p-4 font-mono text-xs text-[var(--color-text-muted)]"> |
| 53 | <strong className="text-[var(--color-text)]">doltgres-first + beta engine.</strong> product |
| 54 | SQL (control + every project) runs on{' '} |
| 55 | <a className="underline" href="/doltgres"> |
| 56 | Doltgres |
| 57 | </a>{' '} |
| 58 | (pre-1.0 — see{' '} |
| 59 | <a className="underline" href="/doltgres/limitations"> |
| 60 | limitations |
| 61 | </a> |
| 62 | ). files use MinIO S3. shell + SDK + HTTP are live; MCP is Pro/Team and project-scoped. |
| 63 | </div> |
| 64 | |
| 65 | {/* ─── path 0: shell lifecycle ─────────────────────────────────────── */} |
| 66 | <h2 className="mt-12 font-mono text-lg">path 0 · from the shell (recommended)</h2> |
| 67 | <p className="mt-3 font-mono text-sm text-[var(--color-text-muted)]"> |
| 68 | two clear commands (do not mix): |
| 69 | </p> |
| 70 | <ul className="mt-2 list-disc pl-5 font-mono text-sm text-[var(--color-text-muted)] space-y-1"> |
| 71 | <li> |
| 72 | <code>briven setup</code> / <code>briven setup my-app</code> — create a{' '} |
| 73 | <em>new</em> cloud project + S3 + wire folder |
| 74 | </li> |
| 75 | <li> |
| 76 | <code>briven connect</code> / <code>briven connect p_…</code> — attach an{' '} |
| 77 | <em>existing</em> project + S3 + wire folder |
| 78 | </li> |
| 79 | </ul> |
| 80 | |
| 81 | <h3 className="mt-6 font-mono text-sm">install the cli (or run one-off)</h3> |
| 82 | <div className="mt-2"> |
| 83 | <PmTabs commands={ONE_SHOT} /> |
| 84 | </div> |
| 85 | <p className="mt-2 font-mono text-xs text-[var(--color-text-subtle)]"> |
| 86 | or install as a dev dependency — full install options on the{' '} |
| 87 | <a className="underline" href="/cli"> |
| 88 | cli |
| 89 | </a>{' '} |
| 90 | page. running bare <code>briven</code> with no linked folder also starts setup. |
| 91 | </p> |
| 92 | |
| 93 | <h3 className="mt-6 font-mono text-sm">new project · briven setup</h3> |
| 94 | <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]"> |
| 95 | opens the browser to sign in, creates a <em>new</em> cloud project, mints CLI + storage |
| 96 | keys, writes <code>briven.json</code> + scaffold, ready to deploy. |
| 97 | </p> |
| 98 | <PmTabs commands={SETUP} /> |
| 99 | <ul className="mt-3 list-disc pl-5 font-mono text-xs text-[var(--color-text-muted)]"> |
| 100 | <li> |
| 101 | <code>briven setup</code> — interactive name / region / optional template |
| 102 | </li> |
| 103 | <li> |
| 104 | <code>--name my-app</code> or positional <code>my-app</code> — create that project |
| 105 | </li> |
| 106 | <li> |
| 107 | <code>--template todo-app</code> — optional starter files only |
| 108 | </li> |
| 109 | <li> |
| 110 | to attach an existing id, use <code>briven connect p_…</code> — not setup |
| 111 | </li> |
| 112 | </ul> |
| 113 | <PmTabs commands={SETUP_THEN} /> |
| 114 | |
| 115 | <h3 className="mt-6 font-mono text-sm">existing project · briven connect</h3> |
| 116 | <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]"> |
| 117 | sign in (if needed), pick or pass a project, mint keys, wire this folder to that project. |
| 118 | </p> |
| 119 | <PmTabs commands={CONNECT} /> |
| 120 | <PmTabs commands={CONNECT_STATUS} /> |
| 121 | |
| 122 | <h3 className="mt-6 font-mono text-sm">full lifecycle (copy-paste)</h3> |
| 123 | <PmTabs commands={LIFECYCLE} /> |
| 124 | |
| 125 | <h3 className="mt-6 font-mono text-sm">step-by-step pieces</h3> |
| 126 | <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]"> |
| 127 | smaller commands for scripts or power users (projects list/create/use, init, link). |
| 128 | </p> |
| 129 | <PmTabs commands={PROJECTS_REMOTE} /> |
| 130 | <PmTabs commands={PROJECTS_CREATE} /> |
| 131 | <PmTabs commands={PROJECTS_USE} /> |
| 132 | <PmTabs commands={PROJECTS_UNLINK} /> |
| 133 | <PmTabs commands={INIT_LINK} /> |
| 134 | |
| 135 | <div className="mt-6 rounded-md border border-[var(--color-border-subtle)] bg-[var(--color-surface)] p-4 font-mono text-xs text-[var(--color-text-muted)]"> |
| 136 | <strong className="text-[var(--color-text)]">credentials.</strong>{' '} |
| 137 | <code>setup</code> / <code>connect</code> store a platform <em>user</em> session and mint a{' '} |
| 138 | <em>project</em> CLI key (+ storage key into <code>.env.local</code> when possible).{' '} |
| 139 | <code>briven logout</code> clears everything; <code>briven connect logout</code> clears only |
| 140 | the platform session. Auth browser keys are separate — see{' '} |
| 141 | <a className="underline" href="/auth"> |
| 142 | auth |
| 143 | </a> |
| 144 | . |
| 145 | </div> |
| 146 | |
| 147 | <p className="mt-4 font-mono text-sm text-[var(--color-text-muted)]"> |
| 148 | self-host? set <code>BRIVEN_API_ORIGIN</code> and <code>BRIVEN_DASHBOARD_ORIGIN</code>{' '} |
| 149 | before <code>setup</code>. details on the{' '} |
| 150 | <a className="underline" href="/cli"> |
| 151 | cli |
| 152 | </a>{' '} |
| 153 | page. |
| 154 | </p> |
| 155 | |
| 156 | <h2 className="mt-12 font-mono text-lg">the three things you need (app / agent paths)</h2> |
| 157 | <p className="mt-3 font-mono text-sm text-[var(--color-text-muted)]"> |
| 158 | open your project in the{' '} |
| 159 | <a className="underline" href="https://briven.tech"> |
| 160 | dashboard |
| 161 | </a>{' '} |
| 162 | and grab these from the project's overview / connect tab: |
| 163 | </p> |
| 164 | <ul className="mt-4 flex flex-col gap-3 font-mono text-sm text-[var(--color-text-muted)]"> |
| 165 | <li className="rounded-md border border-[var(--color-border-subtle)] bg-[var(--color-surface)] p-3"> |
| 166 | <p className="text-[var(--color-text)]">1 · the API endpoint</p> |
| 167 | <p className="mt-1 text-xs"> |
| 168 | the base url your client talks to. for the hosted platform it is{' '} |
| 169 | <code>https://api.briven.tech</code>. this is the <code>apiOrigin</code> the SDK |
| 170 | takes. reactive subscriptions use the matching websocket origin{' '} |
| 171 | <code>wss://ws.briven.tech</code> (<code>wsOrigin</code>). |
| 172 | </p> |
| 173 | </li> |
| 174 | <li className="rounded-md border border-[var(--color-border-subtle)] bg-[var(--color-surface)] p-3"> |
| 175 | <p className="text-[var(--color-text)]">2 · your project id</p> |
| 176 | <p className="mt-1 text-xs"> |
| 177 | looks like <code>p_01HZ…</code>. it scopes every call to your project's data and |
| 178 | functions. |
| 179 | </p> |
| 180 | </li> |
| 181 | <li className="rounded-md border border-[var(--color-border-subtle)] bg-[var(--color-surface)] p-3"> |
| 182 | <p className="text-[var(--color-text)]">3 · an API key</p> |
| 183 | <p className="mt-1 text-xs"> |
| 184 | looks like <code>brk_…</code>. sent on every request as{' '} |
| 185 | <code>Authorization: Bearer brk_…</code>. create one on the project's{' '} |
| 186 | <a className="underline" href="/api-keys"> |
| 187 | api keys |
| 188 | </a>{' '} |
| 189 | page — the plaintext is shown once, so save it immediately. |
| 190 | </p> |
| 191 | </li> |
| 192 | </ul> |
| 193 | |
| 194 | {/* ─── path A: the SDK ─────────────────────────────────────────────── */} |
| 195 | <h2 className="mt-12 font-mono text-lg">path a · the @briven/client SDK (your app)</h2> |
| 196 | <p className="mt-3 font-mono text-sm text-[var(--color-text-muted)]"> |
| 197 | <code>@briven/client</code> is the framework-agnostic JavaScript client. it works in node, |
| 198 | the browser, and any framework. (for react/svelte/vue with ready-made hooks, use the{' '} |
| 199 | <a className="underline" href="/sdks"> |
| 200 | framework clients |
| 201 | </a>{' '} |
| 202 | instead — same idea, less wiring.) |
| 203 | </p> |
| 204 | |
| 205 | <h3 className="mt-6 font-mono text-sm">install</h3> |
| 206 | <div className="mt-2"> |
| 207 | <PmTabs commands={INSTALL_CLIENT} /> |
| 208 | </div> |
| 209 | |
| 210 | <h3 className="mt-6 font-mono text-sm">create a client</h3> |
| 211 | <Snippet>{`import { createBrivenClient } from '@briven/client'; |
| 212 | |
| 213 | const briven = createBrivenClient({ |
| 214 | apiOrigin: 'https://api.briven.tech', // thing 1 — the endpoint |
| 215 | wsOrigin: 'wss://ws.briven.tech', // optional, only needed for subscribe() |
| 216 | projectId: 'p_01HZ...', // thing 2 — your project id |
| 217 | token: process.env.BRIVEN_KEY, // thing 3 — your brk_ api key |
| 218 | });`}</Snippet> |
| 219 | <p className="mt-2 font-mono text-xs text-[var(--color-text-subtle)]"> |
| 220 | <span className="text-[var(--color-text)]">note: </span> |
| 221 | <code>token</code> can also be a function returning a string (or a promise of one) — handy |
| 222 | when you mint short-lived tokens. in the browser, use a <code>viewer</code>-scope key; keep{' '} |
| 223 | <code>developer</code>/<code>admin</code> keys server-side only. |
| 224 | </p> |
| 225 | |
| 226 | <h3 className="mt-6 font-mono text-sm">call a function (node / one-shot)</h3> |
| 227 | <Snippet>{`// invoke runs a deployed function once over HTTP and returns a frame. |
| 228 | const frame = await briven.invoke('listNotes', { limit: 20 }); |
| 229 | |
| 230 | if (frame.ok) { |
| 231 | console.log(frame.value); // the function's return value |
| 232 | console.log(frame.durationMs); // server-side execution time |
| 233 | } else { |
| 234 | console.error(frame.code, frame.message); |
| 235 | }`}</Snippet> |
| 236 | |
| 237 | <h3 className="mt-6 font-mono text-sm">subscribe to live updates (react)</h3> |
| 238 | <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]"> |
| 239 | <code>subscribe</code> calls your handler once with the initial value, then again every |
| 240 | time the rows the function touched change. it needs <code>wsOrigin</code> set. |
| 241 | </p> |
| 242 | <Snippet>{`'use client'; |
| 243 | import { useEffect, useState } from 'react'; |
| 244 | import { createBrivenClient, type InvokeFrame } from '@briven/client'; |
| 245 | |
| 246 | const briven = createBrivenClient({ |
| 247 | apiOrigin: 'https://api.briven.tech', |
| 248 | wsOrigin: 'wss://ws.briven.tech', |
| 249 | projectId: 'p_01HZ...', |
| 250 | token: process.env.NEXT_PUBLIC_BRIVEN_PUBLIC_KEY, // viewer-scope brk_ key |
| 251 | }); |
| 252 | |
| 253 | export function Notes() { |
| 254 | const [notes, setNotes] = useState<{ id: string; body: string }[]>([]); |
| 255 | |
| 256 | useEffect(() => { |
| 257 | const sub = briven.subscribe('listNotes', {}, (frame: InvokeFrame) => { |
| 258 | if (frame.ok) setNotes(frame.value as { id: string; body: string }[]); |
| 259 | }); |
| 260 | return () => sub.close(); // unsubscribe on unmount |
| 261 | }, []); |
| 262 | |
| 263 | return <ul>{notes.map((n) => <li key={n.id}>{n.body}</li>)}</ul>; |
| 264 | }`}</Snippet> |
| 265 | |
| 266 | <h3 className="mt-6 font-mono text-sm">or skip the SDK — call the HTTP endpoint directly</h3> |
| 267 | <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]"> |
| 268 | the SDK's <code>invoke</code> is a thin wrapper over one endpoint. you can call it |
| 269 | from anything that speaks HTTP: |
| 270 | </p> |
| 271 | <Snippet>{`curl -X POST \\ |
| 272 | https://api.briven.tech/v1/projects/p_01HZ.../functions/listNotes \\ |
| 273 | -H "Authorization: Bearer brk_..." \\ |
| 274 | -H "Content-Type: application/json" \\ |
| 275 | -d '{ "limit": 20 }' |
| 276 | |
| 277 | # the request body IS the function's args object. |
| 278 | # response: { "ok": true, "value": ..., "durationMs": 12 } |
| 279 | # or: { "ok": false, "code": "...", "message": "...", "durationMs": 3 }`}</Snippet> |
| 280 | <p className="mt-2 font-mono text-xs text-[var(--color-text-subtle)]"> |
| 281 | the full HTTP surface — deployments, studio, usage, and more — is documented on the{' '} |
| 282 | <a className="underline" href="/api"> |
| 283 | http api |
| 284 | </a>{' '} |
| 285 | page. |
| 286 | </p> |
| 287 | |
| 288 | {/* ─── path B: MCP ─────────────────────────────────────────────────── */} |
| 289 | <h2 className="mt-12 font-mono text-lg">path b · the MCP endpoint (AI agents)</h2> |
| 290 | <p className="mt-3 font-mono text-sm text-[var(--color-text-muted)]"> |
| 291 | MCP (Model Context Protocol) lets an AI coding agent — Claude Code, Cursor, Codex, Gemini |
| 292 | CLI, and others — talk to your project directly: read your schema, query data, manage |
| 293 | functions. briven exposes a streamable-HTTP MCP server at the <code>/mcp</code> path on |
| 294 | your API endpoint. |
| 295 | </p> |
| 296 | |
| 297 | <div className="mt-4 rounded-md border border-[var(--color-warning)] bg-[var(--color-warning)]/10 p-4 font-mono text-xs text-[var(--color-text-muted)]"> |
| 298 | <strong className="text-[var(--color-warning)]">beta + plan-gated.</strong> MCP access is a{' '} |
| 299 | <strong className="text-[var(--color-text)]">Pro / Team</strong> feature, off by default, |
| 300 | and still rolling out. you enable it per project in the dashboard; the platform owner can |
| 301 | also gate it globally. if you don't see the MCP panel, your plan or the platform flag |
| 302 | is the reason. |
| 303 | </div> |
| 304 | |
| 305 | <ol className="mt-6 flex flex-col gap-3 font-mono text-sm text-[var(--color-text-muted)]"> |
| 306 | <li> |
| 307 | <span className="text-[var(--color-text)]">1.</span> in the dashboard, open your |
| 308 | project, go to the <em>MCP</em> / connect panel, and turn MCP access on (Pro/Team only). |
| 309 | </li> |
| 310 | <li> |
| 311 | <span className="text-[var(--color-text)]">2.</span> issue an MCP key. like API keys, the |
| 312 | plaintext is shown once — it looks like <code>pk_briven_mcp_…</code> (a different prefix |
| 313 | from the <code>brk_</code> SDK keys). save it immediately. |
| 314 | </li> |
| 315 | <li> |
| 316 | <span className="text-[var(--color-text)]">3.</span> the panel builds a ready-to-paste |
| 317 | config for your agent. you can scope it read-only and pick which feature groups (docs, |
| 318 | database, functions, storage, branching…) the agent may use. |
| 319 | </li> |
| 320 | </ol> |
| 321 | |
| 322 | <h3 className="mt-6 font-mono text-sm">add it to your agent</h3> |
| 323 | <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]"> |
| 324 | the connection is just a URL plus a bearer header. for example, with Claude Code: |
| 325 | </p> |
| 326 | <Snippet>{`claude mcp add --scope project --transport http briven \\ |
| 327 | "https://api.briven.tech/mcp?project_ref=p_01HZ...&read_only=true"`}</Snippet> |
| 328 | <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]"> |
| 329 | or as a raw MCP client config, with the key in the <code>Authorization</code> header: |
| 330 | </p> |
| 331 | <Snippet>{`{ |
| 332 | "mcpServers": { |
| 333 | "briven": { |
| 334 | "url": "https://api.briven.tech/mcp?project_ref=p_01HZ...", |
| 335 | "headers": { |
| 336 | "Authorization": "Bearer pk_briven_mcp_..." |
| 337 | } |
| 338 | } |
| 339 | } |
| 340 | }`}</Snippet> |
| 341 | <p className="mt-2 font-mono text-xs text-[var(--color-text-subtle)]"> |
| 342 | <span className="text-[var(--color-text)]">note: </span> |
| 343 | the <code>read_only=true</code> query flag restricts the agent to reads; drop it to allow |
| 344 | writes. <code>features=database,functions</code> narrows what the agent can touch. |
| 345 | </p> |
| 346 | |
| 347 | {/* ─── next ────────────────────────────────────────────────────────── */} |
| 348 | <h2 className="mt-12 font-mono text-lg">what to read next</h2> |
| 349 | <ul className="mt-3 flex flex-col gap-2 font-mono text-sm"> |
| 350 | <NextLink |
| 351 | href="/cli" |
| 352 | title="cli reference" |
| 353 | body="every briven command — connect, projects, deploy, dev, env, db, doctor" |
| 354 | /> |
| 355 | <NextLink |
| 356 | href="/quickstart" |
| 357 | title="quickstart" |
| 358 | body="from nothing to a live reactive query in a few minutes" |
| 359 | /> |
| 360 | <NextLink |
| 361 | href="/api-keys" |
| 362 | title="api keys" |
| 363 | body="create, scope, and rotate the brk_ keys the app and manual login paths use" |
| 364 | /> |
| 365 | <NextLink |
| 366 | href="/sdks" |
| 367 | title="client sdks" |
| 368 | body="react, svelte, and vue clients with useQuery/useMutation hooks" |
| 369 | /> |
| 370 | <NextLink |
| 371 | href="/api" |
| 372 | title="http api" |
| 373 | body="every endpoint behind the SDK — deployments, studio, usage, members, billing" |
| 374 | /> |
| 375 | <NextLink |
| 376 | href="/functions" |
| 377 | title="functions" |
| 378 | body="how the query/mutation/action functions you invoke are written and deployed" |
| 379 | /> |
| 380 | </ul> |
| 381 | </DocsShell> |
| 382 | ); |
| 383 | } |
| 384 | |
| 385 | function Snippet({ children }: { children: string }) { |
| 386 | return ( |
| 387 | <pre className="mt-2 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)]"> |
| 388 | <code>{children}</code> |
| 389 | </pre> |
| 390 | ); |
| 391 | } |
| 392 | |
| 393 | function NextLink({ href, title, body }: { href: string; title: string; body: string }) { |
| 394 | return ( |
| 395 | <li> |
| 396 | <a |
| 397 | href={href} |
| 398 | className="block rounded-md border border-[var(--color-border-subtle)] bg-[var(--color-surface)] p-4 transition hover:border-[var(--color-border)]" |
| 399 | > |
| 400 | <p className="font-mono text-[var(--color-text)]">{title}</p> |
| 401 | <p className="mt-1 font-mono text-xs text-[var(--color-text-muted)]">{body}</p> |
| 402 | </a> |
| 403 | </li> |
| 404 | ); |
| 405 | } |