page.tsx122 lines · main
1import { DocsShell } from '../../components/shell';
2
3export const metadata = { title: 'roadmap' };
4
5export default function RoadmapPage() {
6 return (
7 <DocsShell>
8 <h1 className="font-mono text-2xl tracking-tight">roadmap</h1>
9 <p className="mt-2 font-mono text-sm text-[var(--color-text-muted)]">
10 what we&apos;re building, in rough order of priority. dates are intent, not commitment —
11 anything ships when it&apos;s ready and not before. the changelog is what actually
12 landed; this page is what we&apos;re working towards.
13 </p>
14
15 <Phase label="now" body="dogfooding briven on a single VPS, hardening the operator surface, public alpha behind invite codes.">
16 <Bullet status="done">phase 0 — foundations: api, runtime, realtime, dashboard, docs all live</Bullet>
17 <Bullet status="done">phase 1 — reactive queries via LISTEN/NOTIFY across all client SDKs</Bullet>
18 <Bullet status="done">phase 2 — per-tier rate limits, abuse pipeline, audit log, encryption-at-rest for env vars</Bullet>
19 <Bullet status="done">phase 3 — usage metering, beta invite UX, studio CRUD UI, admin triage</Bullet>
20 <Bullet status="done">phase 4 — self-host templates, observability stack, public docs polish, status page</Bullet>
21 <Bullet status="active">deploy on briven&apos;s own VPS, run alpha invitees through the cli + dashboard</Bullet>
22 </Phase>
23
24 <Phase label="next" body="closing the gaps that turn alpha into a product anyone can adopt without hand-holding.">
25 <Bullet status="planned">point-in-time recovery (replace nightly pg_dump with WAL streaming + 7-day window)</Bullet>
26 <Bullet status="planned">multi-region read replicas (eu-west + us-east, opt-in per project)</Bullet>
27 <Bullet status="planned">team auth: SSO via SAML/OIDC, per-project member roles beyond owner/admin/developer</Bullet>
28 <Bullet status="planned">payments live: Polar + invoice PDFs + dunning + tax handling for EU/UK</Bullet>
29 <Bullet status="planned">function logs: full-text search across the last 7 days (today is tail-only)</Bullet>
30 <Bullet status="planned">scheduled functions: cron expressions in code, observable in the dashboard</Bullet>
31 <Bullet status="planned">file uploads: presigned-URL flow + per-project minio bucket + image transforms</Bullet>
32 </Phase>
33
34 <Phase label="later" body="quality-of-life and breadth. nothing here blocks GA but we know we&apos;ll want them.">
35 <Bullet status="planned">first-class python + go SDKs (parity with TS/JS clients)</Bullet>
36 <Bullet status="planned">vector search beyond pgvector — first-party embedding generation via the platform</Bullet>
37 <Bullet status="planned">k8s helm chart for self-hosters past ~100 projects per host</Bullet>
38 <Bullet status="planned">desktop dashboard (electron) for offline-edit + git-based workflows</Bullet>
39 <Bullet status="planned">briven AI: schema-aware function generator, doc-aware chatbot for self-host operators</Bullet>
40 </Phase>
41
42 <Phase label="not on the roadmap" body="things people ask about that we don&apos;t plan to build, with the why.">
43 <Bullet status="rejected">
44 <strong>swappable storage backend (mongo, planetscale, etc.)</strong> — the bet is on
45 postgres. multi-backend is a lot of code for very little user benefit.
46 </Bullet>
47 <Bullet status="rejected">
48 <strong>edge runtime</strong> — deno + cloudflare workers conflict on the network
49 surface; we&apos;d rather invest in regional hosting on real VPSes.
50 </Bullet>
51 <Bullet status="rejected">
52 <strong>proprietary closed-source plugins</strong> — anything we ship lives in the
53 public repo, even if AGPL is incompatible with your use case (we sell exemptions).
54 </Bullet>
55 </Phase>
56
57 <p className="mt-12 font-mono text-xs text-[var(--color-text-subtle)]">
58 miss something? open an issue on{' '}
59 <a href="https://codeberg.org/flndrn/briven" className="underline">
60 codeberg.org/flndrn/briven
61 </a>
62 .
63 </p>
64 </DocsShell>
65 );
66}
67
68function Phase({
69 label,
70 body,
71 children,
72}: {
73 label: string;
74 body: string;
75 children: React.ReactNode;
76}) {
77 return (
78 <section className="mt-10">
79 <h2 className="font-mono text-lg uppercase tracking-[0.12em] text-[var(--color-primary)]">
80 {label}
81 </h2>
82 <p className="mt-1 font-mono text-sm text-[var(--color-text-muted)]">{body}</p>
83 <ul className="mt-4 space-y-2 font-mono text-sm">{children}</ul>
84 </section>
85 );
86}
87
88function Bullet({
89 status,
90 children,
91}: {
92 status: 'done' | 'active' | 'planned' | 'rejected';
93 children: React.ReactNode;
94}) {
95 const tag =
96 status === 'done'
97 ? 'done'
98 : status === 'active'
99 ? 'now '
100 : status === 'planned'
101 ? 'next'
102 : 'no ';
103 const colour =
104 status === 'done'
105 ? 'var(--color-text-subtle)'
106 : status === 'active'
107 ? 'var(--color-primary)'
108 : status === 'planned'
109 ? 'var(--color-text-muted)'
110 : 'var(--color-text-subtle)';
111 return (
112 <li className="flex items-start gap-3">
113 <span
114 className="font-mono text-[10px] uppercase tracking-[0.12em]"
115 style={{ color: colour, paddingTop: 2 }}
116 >
117 [{tag}]
118 </span>
119 <span className="text-[var(--color-text-muted)]">{children}</span>
120 </li>
121 );
122}