Skip to content

Commit b18b03c

Browse files
authored
Upgrade web to Next 16 + Tailwind v4, add Vercel Analytics (#12)
1 parent acac367 commit b18b03c

21 files changed

Lines changed: 1991 additions & 1412 deletions

web/.eslintrc.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

web/README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
# siphon web — landing page & docs
22

33
The marketing landing page and documentation site for siphon, built with
4-
Next.js (App Router) + Tailwind and deployed on Vercel. The docs pages render
5-
the repository's own `docs/*.md` at build time, so the site never drifts from
6-
the shipped documentation.
4+
Next.js 16 (App Router, Turbopack) + React 19 + Tailwind CSS v4 and deployed on
5+
Vercel. The docs pages render the repository's own `docs/*.md` at build time, so
6+
the site never drifts from the shipped documentation.
7+
8+
Tailwind v4 is configured CSS-first: there is no `tailwind.config.*`. The design
9+
tokens live as CSS variables in `app/globals.css` (imported via
10+
`@import "tailwindcss"`), and the PostCSS plugin is `@tailwindcss/postcss`.
711

812
## Develop
913

1014
```bash
1115
cd web
1216
npm install
13-
npm run dev # http://localhost:3000
14-
npm run build # production build (also what Vercel runs)
17+
npm run dev # http://localhost:3000 (Turbopack)
18+
npm run build # production build with Turbopack (also what Vercel runs)
1519

1620
npm run lint # ESLint
1721
npm run lint:fix # ESLint, autofix

web/app/docs/page.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ export default function DocsIndex() {
1818
<main>
1919
<p className="eyebrow mb-3">documentation</p>
2020
<h1 className="mb-4 text-4xl">Concepts &amp; guides</h1>
21-
<p className="mb-8 max-w-2xl leading-relaxed text-[var(--muted)]">
21+
<p className="mb-8 max-w-2xl leading-relaxed text-(--muted)">
2222
Everything you need to run siphon in anger — from your first backup to continuous
2323
cross-engine replication. These pages render the same Markdown that ships in the repository,
2424
so they track the latest source.
2525
</p>
2626

2727
{/* Quick start: get someone to a working install without leaving the
2828
Overview, then point them at the first guide. */}
29-
<div className="mb-12 rounded-xl border border-[var(--line)] bg-[var(--ink-2)] p-6">
29+
<div className="mb-12 rounded-xl border border-(--line) bg-(--ink-2) p-6">
3030
<p className="eyebrow mb-3">quick start</p>
31-
<p className="mb-4 max-w-xl text-sm leading-relaxed text-[var(--muted)]">
31+
<p className="mb-4 max-w-xl text-sm leading-relaxed text-(--muted)">
3232
Install the binary, then head to{" "}
33-
<Link href="/docs/getting-started" className="text-[var(--flow)]">
33+
<Link href="/docs/getting-started" className="text-(--flow)">
3434
Getting started
3535
</Link>{" "}
3636
for your first backup and sync.
@@ -53,31 +53,31 @@ export default function DocsIndex() {
5353
<Link
5454
key={d.slug}
5555
href={`/docs/${d.slug}`}
56-
className="bg-[var(--ink-2)]/40 group block rounded-xl border border-[var(--line)] p-5 no-underline transition-colors hover:border-[var(--flow)] hover:bg-[var(--ink-2)] hover:no-underline"
56+
className="group block rounded-xl border border-(--line) bg-(--ink-2)/40 p-5 no-underline transition-colors hover:border-(--flow) hover:bg-(--ink-2) hover:no-underline"
5757
>
58-
<span className="flex items-center gap-2 text-lg font-semibold text-[var(--paper)]">
58+
<span className="flex items-center gap-2 text-lg font-semibold text-(--paper)">
5959
{d.title}
60-
<span className="text-[var(--flow)] opacity-0 transition-all group-hover:translate-x-0.5 group-hover:opacity-100">
60+
<span className="text-(--flow) opacity-0 transition-all group-hover:translate-x-0.5 group-hover:opacity-100">
6161
6262
</span>
6363
</span>
64-
<p className="mt-1.5 text-sm leading-relaxed text-[var(--muted)]">{d.blurb}</p>
64+
<p className="mt-1.5 text-sm leading-relaxed text-(--muted)">{d.blurb}</p>
6565
</Link>
6666
))}
6767
</div>
6868
</section>
6969
);
7070
})}
7171

72-
<div className="mt-12 flex flex-col gap-3 border-t border-[var(--line)] pt-8 text-sm text-[var(--muted)] sm:flex-row sm:items-center sm:justify-between">
72+
<div className="mt-12 flex flex-col gap-3 border-t border-(--line) pt-8 text-sm text-(--muted) sm:flex-row sm:items-center sm:justify-between">
7373
<span>
7474
Found a gap or a bug?{" "}
75-
<ExtLink href={`${REPO_URL}/issues`} className="text-[var(--flow)]">
75+
<ExtLink href={`${REPO_URL}/issues`} className="text-(--flow)">
7676
Open an issue
7777
</ExtLink>
7878
.
7979
</span>
80-
<ExtLink href={REPO_URL} className="text-[var(--flow)]">
80+
<ExtLink href={REPO_URL} className="text-(--flow)">
8181
Browse the source ↗
8282
</ExtLink>
8383
</div>

web/app/globals.css

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
@tailwind base;
2-
@tailwind components;
3-
@tailwind utilities;
1+
@import "tailwindcss";
42

53
/* ── siphon design system ───────────────────────────────────────────────
64
Thesis: "the pipe." siphon moves data through a conduit, so the visual
@@ -21,8 +19,8 @@
2119
--muted: #7e8ca3;
2220
--line: #25324d;
2321

24-
--font-sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial,
25-
sans-serif;
22+
--font-sans:
23+
ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
2624
--font-mono: ui-monospace, "SF Mono", "JetBrains Mono", "Fira Code", Menlo, Consolas, monospace;
2725
}
2826

@@ -187,7 +185,8 @@
187185
}
188186
}
189187
.flowgrid {
190-
background-image: linear-gradient(var(--line) 1px, transparent 1px),
188+
background-image:
189+
linear-gradient(var(--line) 1px, transparent 1px),
191190
linear-gradient(90deg, var(--line) 1px, transparent 1px);
192191
background-size:
193192
56px 56px,

web/app/layout.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Metadata } from "next";
2+
import { Analytics } from "@vercel/analytics/next";
23
import "./globals.css";
34
import {
45
SITE_URL,
@@ -100,6 +101,10 @@ export default function RootLayout({ children }: { children: React.ReactNode })
100101
// Structured data is static, build-time JSON — safe to inline.
101102
dangerouslySetInnerHTML={{ __html: JSON.stringify(JSON_LD) }}
102103
/>
104+
{/* Vercel Web Analytics — privacy-friendly (no cookies). A no-op unless
105+
deployed on Vercel with Analytics enabled, so it won't affect the
106+
static build or non-Vercel hosting. */}
107+
<Analytics />
103108
</body>
104109
</html>
105110
);

web/app/page.tsx

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ export default function Home() {
8080
<div>
8181
<p className="eyebrow rise mb-5">backup · restore · sync · cdc</p>
8282
<h1
83-
className="rise text-balance text-[2.6rem] leading-[1.05] sm:text-6xl"
83+
className="rise text-[2.6rem] leading-[1.05] text-balance sm:text-6xl"
8484
style={{ "--rise-delay": "80ms" } as React.CSSProperties}
8585
>
8686
Sync any database,
8787
<br />
88-
<span className="bg-gradient-to-r from-[var(--flow)] to-[var(--flow-2)] bg-clip-text text-transparent">
88+
<span className="bg-linear-to-r from-(--flow) to-(--flow-2) bg-clip-text text-transparent">
8989
anywhere.
9090
</span>
9191
</h1>
@@ -94,8 +94,8 @@ export default function Home() {
9494
style={{ "--rise-delay": "160ms" } as React.CSSProperties}
9595
>
9696
One binary that turns the painful sprawl of{" "}
97-
<code className="mono text-sm text-[var(--flow)]">pg_dump → pg_restore</code> shell
98-
scripts into a guided, observable workflow — across PostgreSQL, MySQL, and MariaDB.
97+
<code className="mono text-sm text-(--flow)">pg_dump → pg_restore</code> shell scripts
98+
into a guided, observable workflow — across PostgreSQL, MySQL, and MariaDB.
9999
</p>
100100
<div className="rise mt-8" style={{ "--rise-delay": "240ms" } as React.CSSProperties}>
101101
<HeroInstall />
@@ -106,13 +106,13 @@ export default function Home() {
106106
>
107107
<Link
108108
href="/docs"
109-
className="rounded-lg bg-[var(--flow)] px-5 py-3 font-medium text-[var(--ink)] no-underline transition-opacity hover:no-underline hover:opacity-90"
109+
className="rounded-lg bg-(--flow) px-5 py-3 font-medium text-(--ink) no-underline transition-opacity hover:no-underline hover:opacity-90"
110110
>
111111
Read the docs
112112
</Link>
113113
<ExtLink
114114
href={REPO_URL}
115-
className="rounded-lg border border-[var(--line)] px-5 py-3 font-medium text-[var(--paper)] no-underline transition-colors hover:border-[var(--flow)] hover:no-underline"
115+
className="rounded-lg border border-(--line) px-5 py-3 font-medium text-(--paper) no-underline transition-colors hover:border-(--flow) hover:no-underline"
116116
>
117117
View source ↗
118118
</ExtLink>
@@ -128,15 +128,15 @@ export default function Home() {
128128
<section className="mx-auto max-w-6xl px-6 py-12">
129129
<p className="eyebrow mb-3">how it flows</p>
130130
<h2 className="mb-10 max-w-2xl text-3xl">Three verbs, one conduit</h2>
131-
<div className="grid gap-px overflow-hidden rounded-xl border border-[var(--line)] bg-[var(--line)] md:grid-cols-3">
131+
<div className="grid gap-px overflow-hidden rounded-xl border border-(--line) bg-(--line) md:grid-cols-3">
132132
{FLOW.map((s, i) => (
133-
<Reveal key={s.n} delay={i * 90} className="bg-[var(--ink)]">
133+
<Reveal key={s.n} delay={i * 90} className="bg-(--ink)">
134134
<article className="flex h-full flex-col p-6">
135-
<span className="mono text-3xl font-bold text-[var(--flow)]">{s.n}</span>
135+
<span className="mono text-3xl font-bold text-(--flow)">{s.n}</span>
136136
<h3 className="mt-4 text-xl">{s.title}</h3>
137-
<p className="mt-2 flex-1 text-sm leading-relaxed text-[var(--muted)]">{s.body}</p>
138-
<code className="mt-4 block rounded-md border border-[var(--line)] bg-[#0a111e] px-3 py-2 font-mono text-xs text-[var(--paper)]">
139-
<span className="text-[var(--amber)]">$ </span>
137+
<p className="mt-2 flex-1 text-sm leading-relaxed text-(--muted)">{s.body}</p>
138+
<code className="mt-4 block rounded-md border border-(--line) bg-[#0a111e] px-3 py-2 font-mono text-xs text-(--paper)">
139+
<span className="text-(--amber)">$ </span>
140140
{s.cmd}
141141
</code>
142142
</article>
@@ -151,13 +151,13 @@ export default function Home() {
151151
<p className="eyebrow mb-10">what it does</p>
152152
<div className="flex gap-8">
153153
<div className="flowline hidden shrink-0 sm:block" aria-hidden />
154-
<div className="grid gap-px overflow-hidden rounded-xl border border-[var(--line)] bg-[var(--line)] sm:grid-cols-2">
154+
<div className="grid gap-px overflow-hidden rounded-xl border border-(--line) bg-(--line) sm:grid-cols-2">
155155
{FEATURES.map((f, i) => (
156-
<Reveal key={f.label} delay={(i % 2) * 90} className="bg-[var(--ink)]">
156+
<Reveal key={f.label} delay={(i % 2) * 90} className="bg-(--ink)">
157157
<article className="p-6">
158158
<p className="eyebrow mb-3">{f.label}</p>
159159
<h3 className="mb-2 text-xl">{f.title}</h3>
160-
<p className="text-sm leading-relaxed text-[var(--muted)]">{f.body}</p>
160+
<p className="text-sm leading-relaxed text-(--muted)">{f.body}</p>
161161
</article>
162162
</Reveal>
163163
))}
@@ -167,10 +167,10 @@ export default function Home() {
167167

168168
{/* Engines strip: the three databases siphon speaks, stated once. */}
169169
<section className="mx-auto max-w-6xl px-6 py-12">
170-
<div className="flex flex-col items-start justify-between gap-6 rounded-xl border border-[var(--line)] bg-[var(--ink-2)] p-8 sm:flex-row sm:items-center">
170+
<div className="flex flex-col items-start justify-between gap-6 rounded-xl border border-(--line) bg-(--ink-2) p-8 sm:flex-row sm:items-center">
171171
<div>
172172
<p className="eyebrow mb-2">speaks natively</p>
173-
<p className="max-w-md text-sm leading-relaxed text-[var(--muted)]">
173+
<p className="max-w-md text-sm leading-relaxed text-(--muted)">
174174
First-class drivers for each engine — same commands, engine-aware quoting, types, and
175175
change capture under the hood.
176176
</p>
@@ -179,7 +179,7 @@ export default function Home() {
179179
{ENGINES.map((e) => (
180180
<span
181181
key={e}
182-
className="rounded-full border border-[var(--line)] bg-[var(--ink)] px-4 py-2 font-mono text-sm text-[var(--flow)]"
182+
className="rounded-full border border-(--line) bg-(--ink) px-4 py-2 font-mono text-sm text-(--flow)"
183183
>
184184
{e}
185185
</span>
@@ -194,29 +194,29 @@ export default function Home() {
194194
<h2 className="mb-8 text-3xl">Up and running in one line</h2>
195195
<div className="space-y-6">
196196
<div>
197-
<p className="mb-2 font-mono text-xs uppercase tracking-widest text-[var(--muted)]">
197+
<p className="mb-2 font-mono text-xs tracking-widest text-(--muted) uppercase">
198198
Linux · macOS
199199
</p>
200200
<InstallCommand command={INSTALL_CMD} />
201201
</div>
202202
<div className="grid gap-6 sm:grid-cols-2">
203203
<div>
204-
<p className="mb-2 font-mono text-xs uppercase tracking-widest text-[var(--muted)]">
204+
<p className="mb-2 font-mono text-xs tracking-widest text-(--muted) uppercase">
205205
Homebrew
206206
</p>
207207
<InstallCommand command="brew install nixrajput/siphon/siphon" />
208208
</div>
209209
<div>
210-
<p className="mb-2 font-mono text-xs uppercase tracking-widest text-[var(--muted)]">
210+
<p className="mb-2 font-mono text-xs tracking-widest text-(--muted) uppercase">
211211
Scoop (Windows)
212212
</p>
213213
<InstallCommand command="scoop install siphon" />
214214
</div>
215215
</div>
216-
<p className="text-sm text-[var(--muted)]">
217-
Prefer source? <code className="mono text-[var(--flow)]">go install</code> the module,
218-
or grab a prebuilt binary from <ExtLink href={`${REPO_URL}/releases`}>Releases</ExtLink>
219-
. Every archive has a SHA-256 checksum, and the checksum file is cosign-signed.
216+
<p className="text-sm text-(--muted)">
217+
Prefer source? <code className="mono text-(--flow)">go install</code> the module, or
218+
grab a prebuilt binary from <ExtLink href={`${REPO_URL}/releases`}>Releases</ExtLink>.
219+
Every archive has a SHA-256 checksum, and the checksum file is cosign-signed.
220220
</p>
221221
</div>
222222
</section>

0 commit comments

Comments
 (0)