Skip to content

Commit 28a7c89

Browse files
committed
feat: add website
1 parent 5e7a1fb commit 28a7c89

5 files changed

Lines changed: 471 additions & 257 deletions

File tree

website/src/App.tsx

Lines changed: 55 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,19 @@ export function App() {
3939

4040
return (
4141
<div className="page-shell min-h-screen bg-background text-foreground">
42-
{/* Header */}
43-
<header className="fixed top-0 left-0 right-0 z-50 glass border-b border-border/30">
44-
<div className="max-w-6xl mx-auto flex items-center justify-between gap-3 px-6 h-14">
45-
<a href="/" className="font-mono font-bold text-lg tracking-tight">
46-
<span className="gradient-text">RSQL</span>
42+
<header className="fixed inset-x-0 top-0 z-50 border-b border-border/45 bg-background/62 backdrop-blur-md">
43+
<div className="mx-auto flex h-16 max-w-6xl items-center justify-between gap-3 px-6">
44+
<a href="/" className="flex items-center gap-3">
45+
<span className="font-mono text-lg font-bold tracking-tight">
46+
<span className="gradient-text">RSQL</span>
47+
</span>
48+
<span className="hidden text-[12px] text-muted-foreground md:inline">
49+
PostgreSQL Workbench
50+
</span>
4751
</a>
48-
<nav className="hidden md:flex items-center gap-6 text-sm text-muted-foreground">
52+
<nav className="hidden md:flex items-center gap-6 text-[13px] text-muted-foreground">
4953
<a href="#features" className="hover:text-foreground transition-colors">Features</a>
50-
<a href="#demo" className="hover:text-foreground transition-colors">Demo</a>
54+
<a href="#demo" className="hover:text-foreground transition-colors">Sandbox</a>
5155
<a
5256
href="https://github.com/rust-dd/rust-sql"
5357
target="_blank"
@@ -64,29 +68,19 @@ export function App() {
6468
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
6569
aria-label={`Switch to ${theme === "dark" ? "light" : "dark"} mode`}
6670
title={`Switch to ${theme === "dark" ? "light" : "dark"} mode`}
67-
className="relative inline-flex h-9 w-[4.5rem] items-center justify-between rounded-full border border-border/70 bg-card/70 px-2.5 text-muted-foreground transition-colors hover:text-foreground"
71+
className="link-chip inline-flex h-9 w-9 items-center justify-center rounded-full text-muted-foreground"
6872
>
69-
<span
70-
className={`absolute top-1 h-7 w-7 rounded-full bg-primary/12 transition-transform duration-300 ${
71-
theme === "light" ? "translate-x-0" : "translate-x-9"
72-
}`}
73-
/>
74-
<Sun
75-
className={`relative z-10 h-3.5 w-3.5 transition-colors ${
76-
theme === "light" ? "text-primary" : "text-muted-foreground/70"
77-
}`}
78-
/>
79-
<Moon
80-
className={`relative z-10 h-3.5 w-3.5 transition-colors ${
81-
theme === "dark" ? "text-primary" : "text-muted-foreground/70"
82-
}`}
83-
/>
73+
{theme === "dark" ? (
74+
<Sun className="h-4 w-4" />
75+
) : (
76+
<Moon className="h-4 w-4" />
77+
)}
8478
</button>
8579
<a
8680
href="https://github.com/rust-dd/rust-sql/releases/latest"
8781
target="_blank"
8882
rel="noopener noreferrer"
89-
className="gradient-btn rounded-md px-4 py-1.5 text-xs font-semibold text-white inline-flex items-center gap-1.5"
83+
className="gradient-btn inline-flex items-center gap-1.5 rounded-full px-4 py-1.5 text-xs font-semibold text-white"
9084
>
9185
<Download className="h-3.5 w-3.5" />
9286
<span className="hidden sm:inline">Download</span>
@@ -101,38 +95,43 @@ export function App() {
10195
<Demo />
10296
</main>
10397

104-
{/* Footer */}
105-
<footer className="border-t border-border/30 py-12 px-6">
106-
<div className="max-w-6xl mx-auto flex flex-col md:flex-row items-center justify-between gap-4 text-sm text-muted-foreground">
107-
<span className="font-mono">
108-
<span className="gradient-text font-bold">RSQL</span> — Open source PostgreSQL client
109-
</span>
110-
<div className="flex items-center gap-6">
111-
<a
112-
href="https://github.com/rust-dd/rust-sql"
113-
target="_blank"
114-
rel="noopener noreferrer"
115-
className="hover:text-foreground transition-colors inline-flex items-center gap-1.5"
116-
>
117-
<Github className="h-4 w-4" />
118-
Source Code
119-
</a>
120-
<a
121-
href="https://github.com/rust-dd/rust-sql/releases"
122-
target="_blank"
123-
rel="noopener noreferrer"
124-
className="hover:text-foreground transition-colors"
125-
>
126-
Releases
127-
</a>
128-
<a
129-
href="https://github.com/rust-dd/rust-sql/issues"
130-
target="_blank"
131-
rel="noopener noreferrer"
132-
className="hover:text-foreground transition-colors"
133-
>
134-
Issues
135-
</a>
98+
<footer className="px-6 pb-10 pt-4">
99+
<div className="mx-auto max-w-6xl border-t border-border/50 pt-8">
100+
<div className="flex flex-col gap-6 md:flex-row md:items-center md:justify-between">
101+
<div className="flex items-center gap-3">
102+
<span className="font-mono text-lg font-bold tracking-tight">
103+
<span className="gradient-text">RSQL</span>
104+
</span>
105+
<span className="text-sm text-muted-foreground">
106+
Open source PostgreSQL client
107+
</span>
108+
</div>
109+
<div className="flex flex-wrap gap-2 text-sm text-muted-foreground">
110+
<a
111+
href="https://github.com/rust-dd/rust-sql"
112+
target="_blank"
113+
rel="noopener noreferrer"
114+
className="link-chip rounded-full px-4 py-2.5"
115+
>
116+
Source Code
117+
</a>
118+
<a
119+
href="https://github.com/rust-dd/rust-sql/releases"
120+
target="_blank"
121+
rel="noopener noreferrer"
122+
className="link-chip rounded-full px-4 py-2.5"
123+
>
124+
Releases
125+
</a>
126+
<a
127+
href="https://github.com/rust-dd/rust-sql/issues"
128+
target="_blank"
129+
rel="noopener noreferrer"
130+
className="link-chip rounded-full px-4 py-2.5"
131+
>
132+
Issues
133+
</a>
134+
</div>
136135
</div>
137136
</div>
138137
</footer>

website/src/components/Demo.tsx

Lines changed: 121 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -107,110 +107,133 @@ export function Demo() {
107107

108108
return (
109109
<section className="px-6 py-24 max-w-6xl mx-auto" id="demo">
110-
<h2 className="text-3xl md:text-4xl font-bold text-center mb-4">
111-
Try it in your browser
112-
</h2>
113-
<p className="text-center text-muted-foreground mb-10 max-w-xl mx-auto">
114-
Full PostgreSQL running in WebAssembly. Write real SQL — no server needed.
115-
</p>
110+
<div className="border-t border-border/45 pt-10">
111+
<div className="mb-8 max-w-3xl">
112+
<p className="section-label mb-3">
113+
In-browser sandbox
114+
</p>
115+
<h2 className="font-display text-[2.6rem] leading-[0.96] md:text-[3.9rem]">
116+
Touch the flow
117+
<br />
118+
before you
119+
<br />
120+
install it.
121+
</h2>
122+
<p className="mt-4 text-base leading-relaxed text-muted-foreground">
123+
Full PostgreSQL running in WebAssembly. Real SQL, seeded data, no setup friction.
124+
</p>
116125

117-
{/* Sample query buttons */}
118-
<div className="flex flex-wrap justify-center gap-2 mb-6">
119-
{SAMPLE_QUERIES.map((q) => (
120-
<button
121-
key={q.label}
122-
onClick={() => {
123-
setSql(q.sql);
124-
executeMutation.mutate(q.sql, {
125-
onSuccess: (data) => setResult(data),
126-
});
127-
}}
128-
className={`rounded-full border px-3 py-1 text-xs font-mono transition-colors ${
129-
sql === q.sql
130-
? "border-primary bg-primary/10 text-primary"
131-
: "border-border bg-card/60 text-muted-foreground hover:text-foreground hover:border-muted-foreground/50"
132-
}`}
133-
>
134-
{q.label}
135-
</button>
136-
))}
137-
</div>
138-
139-
{/* Demo window */}
140-
<div className="glass rounded-xl overflow-hidden shadow-2xl shadow-primary/5 mx-auto max-w-5xl">
141-
{/* Title bar */}
142-
<div className="flex items-center gap-2 px-4 py-2.5 bg-card/80 border-b border-border/50">
143-
<div className="flex gap-1.5">
144-
<span className="h-3 w-3 rounded-full bg-red-500/80" />
145-
<span className="h-3 w-3 rounded-full bg-yellow-500/80" />
146-
<span className="h-3 w-3 rounded-full bg-green-500/80" />
147-
</div>
148-
<span className="flex-1 text-center text-xs text-muted-foreground font-mono">
149-
RSQL — PostgreSQL (WebAssembly)
150-
</span>
151-
<button
152-
onClick={() => resetMutation.mutate()}
153-
className="text-muted-foreground hover:text-foreground transition-colors"
154-
title="Reset database"
155-
>
156-
<RotateCcw className="h-3.5 w-3.5" />
157-
</button>
158-
</div>
159-
160-
{/* Content area */}
161-
<div className="flex h-[480px]">
162-
{/* Sidebar */}
163-
<DemoSidebar
164-
onTableClick={(table) => {
165-
const q = `SELECT * FROM ${table} LIMIT 100;`;
166-
setSql(q);
167-
executeMutation.mutate(q, {
168-
onSuccess: (data) => setResult(data),
169-
});
170-
}}
171-
/>
172-
173-
{/* Main area */}
174-
<div className="flex-1 flex flex-col min-w-0">
175-
{/* Toolbar */}
176-
<div className="flex items-center gap-2 px-3 py-1.5 border-b border-border/50 bg-card/40">
126+
<div className="mt-6 flex flex-wrap gap-2">
127+
{SAMPLE_QUERIES.map((q) => (
177128
<button
178-
onClick={execute}
179-
disabled={executeMutation.isPending}
180-
className="gradient-btn inline-flex items-center gap-1.5 rounded-md px-3 py-1 text-xs font-semibold text-white disabled:opacity-50"
129+
key={q.label}
130+
onClick={() => {
131+
setSql(q.sql);
132+
executeMutation.mutate(q.sql, {
133+
onSuccess: (data) => setResult(data),
134+
});
135+
}}
136+
className={`rounded-full border px-4 py-2 text-left text-xs font-mono transition-colors ${
137+
sql === q.sql
138+
? "border-primary bg-primary/10 text-primary"
139+
: "border-border bg-card/60 text-muted-foreground hover:text-foreground hover:border-muted-foreground/50"
140+
}`}
181141
>
182-
{executeMutation.isPending ? (
183-
<Loader2 className="h-3 w-3 animate-spin" />
184-
) : (
185-
<Play className="h-3 w-3" />
186-
)}
187-
Execute
142+
{q.label}
188143
</button>
189-
<span className="text-[10px] text-muted-foreground font-mono ml-auto">
190-
{result
191-
? result.error
192-
? "Error"
193-
: `${result.rowCount} rows in ${result.time.toFixed(1)}ms`
194-
: "⌘+Enter to run"}
195-
</span>
144+
))}
145+
</div>
146+
147+
<div className="mt-6 grid gap-3 border-t border-border/40 pt-4 sm:grid-cols-3">
148+
<div>
149+
<div className="font-mono text-[10px] uppercase tracking-[0.24em] text-muted-foreground">
150+
Engine
151+
</div>
152+
<div className="mt-2 text-sm text-foreground">PGlite</div>
153+
</div>
154+
<div>
155+
<div className="font-mono text-[10px] uppercase tracking-[0.24em] text-muted-foreground">
156+
Dataset
157+
</div>
158+
<div className="mt-2 text-sm text-foreground">Seeded demo schema</div>
159+
</div>
160+
<div>
161+
<div className="font-mono text-[10px] uppercase tracking-[0.24em] text-muted-foreground">
162+
Setup
163+
</div>
164+
<div className="mt-2 text-sm text-foreground">Zero install</div>
196165
</div>
166+
</div>
167+
</div>
197168

198-
{/* Editor */}
199-
<div className="relative flex-none h-[180px] border-b border-border/50">
200-
<textarea
201-
ref={textareaRef}
202-
value={sql}
203-
onChange={(e) => setSql(e.target.value)}
204-
onKeyDown={handleKeyDown}
205-
spellCheck={false}
206-
className="w-full h-full resize-none bg-[var(--editor-bg)] text-foreground font-mono text-[13px] leading-6 p-4 focus:outline-none"
207-
placeholder="Write your SQL here..."
208-
/>
169+
<div className="section-frame overflow-hidden rounded-[28px]">
170+
<div className="flex items-center gap-2 px-4 py-2.5 bg-card/80 border-b border-border/50">
171+
<div className="flex gap-1.5">
172+
<span className="h-3 w-3 rounded-full bg-red-500/80" />
173+
<span className="h-3 w-3 rounded-full bg-yellow-500/80" />
174+
<span className="h-3 w-3 rounded-full bg-green-500/80" />
209175
</div>
176+
<span className="flex-1 text-center text-xs text-muted-foreground font-mono">
177+
RSQL — browser.sandbox
178+
</span>
179+
<button
180+
onClick={() => resetMutation.mutate()}
181+
className="text-muted-foreground hover:text-foreground transition-colors"
182+
title="Reset database"
183+
>
184+
<RotateCcw className="h-3.5 w-3.5" />
185+
</button>
186+
</div>
187+
188+
<div className="flex h-[480px]">
189+
<DemoSidebar
190+
onTableClick={(table) => {
191+
const q = `SELECT * FROM ${table} LIMIT 100;`;
192+
setSql(q);
193+
executeMutation.mutate(q, {
194+
onSuccess: (data) => setResult(data),
195+
});
196+
}}
197+
/>
198+
199+
<div className="flex-1 flex flex-col min-w-0">
200+
<div className="flex items-center gap-2 px-3 py-1.5 border-b border-border/50 bg-card/40">
201+
<button
202+
onClick={execute}
203+
disabled={executeMutation.isPending}
204+
className="gradient-btn inline-flex items-center gap-1.5 rounded-md px-3 py-1 text-xs font-semibold text-white disabled:opacity-50"
205+
>
206+
{executeMutation.isPending ? (
207+
<Loader2 className="h-3 w-3 animate-spin" />
208+
) : (
209+
<Play className="h-3 w-3" />
210+
)}
211+
Execute
212+
</button>
213+
<span className="text-[10px] text-muted-foreground font-mono ml-auto">
214+
{result
215+
? result.error
216+
? "Error"
217+
: `${result.rowCount} rows in ${result.time.toFixed(1)}ms`
218+
: "⌘+Enter to run"}
219+
</span>
220+
</div>
210221

211-
{/* Results */}
212-
<div className="flex-1 overflow-auto">
213-
{result && <DemoResults result={result} />}
222+
<div className="relative flex-none h-[180px] border-b border-border/50">
223+
<textarea
224+
ref={textareaRef}
225+
value={sql}
226+
onChange={(e) => setSql(e.target.value)}
227+
onKeyDown={handleKeyDown}
228+
spellCheck={false}
229+
className="w-full h-full resize-none bg-[var(--editor-bg)] text-foreground font-mono text-[13px] leading-6 p-4 focus:outline-none"
230+
placeholder="Write your SQL here..."
231+
/>
232+
</div>
233+
234+
<div className="flex-1 overflow-auto">
235+
{result && <DemoResults result={result} />}
236+
</div>
214237
</div>
215238
</div>
216239
</div>
@@ -357,11 +380,11 @@ function DemoResults({ result }: { result: QueryResult }) {
357380
return (
358381
<table className="w-full text-left font-mono text-[12px] border-collapse">
359382
<thead>
360-
<tr className="bg-muted/50 sticky top-0">
383+
<tr>
361384
{result.columns.map((col) => (
362385
<th
363386
key={col}
364-
className="px-3 py-1.5 text-[11px] font-semibold text-muted-foreground border-b border-r border-border/30 whitespace-nowrap"
387+
className="sticky top-0 z-10 border-b border-r border-border/30 bg-card px-3 py-1.5 text-[11px] font-semibold whitespace-nowrap text-muted-foreground"
365388
>
366389
{col}
367390
</th>

0 commit comments

Comments
 (0)