Skip to content

Commit 0019314

Browse files
Ajit Pratap Singhclaude
authored andcommitted
fix(website): comprehensive audit fixes — phase 2 & 3
Homepage: - Fix invalid double <main> nesting (layout.tsx wraps in <div> now) - StatsBar: grid layout prevents 3+1 orphan at tablet breakpoints - StatsBar: unify performance stat to 1,380,000 (matches benchmarks page) - Hero: improve hover contrast and mobile overflow handling - McpSection: fix badge contrast (zinc-500→zinc-300), add MCP guide CTA Playground: - SqlEditor: CodeMirror fills container height via theme + h-full wrapper - Playground: skeleton loading state mirrors real UI layout - FormatTab: consistent overflow handling - AnalyzeTab: C:0 H:0 M:0 L:0 severity format with hover tooltip Benchmarks: - Section heading, GoSQLX highlight row, CTA section - Accessible aria-labels on ✓/✗ symbols - Mobile swipe hint, improved dot contrast, last-updated label - Updated page title with 1.38M ops/sec Docs: - TOC width: w-48 → w-56 (224px) for better readability Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 00aded0 commit 0019314

11 files changed

Lines changed: 127 additions & 34 deletions

File tree

website/src/app/benchmarks/BenchmarksContent.tsx

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22

3+
import Link from 'next/link';
34
import { FadeIn } from '@/components/ui/FadeIn';
45
import { GlassCard } from '@/components/ui/GlassCard';
56

@@ -38,6 +39,9 @@ export function BenchmarksContent() {
3839
<p className="mt-4 text-lg text-zinc-400 max-w-2xl mx-auto">
3940
Real-world performance data from the GoSQLX parser, measured on production-grade hardware.
4041
</p>
42+
<p className="mt-3 text-xs text-zinc-500">
43+
Last updated: March 2026 &middot; Based on v1.12.1
44+
</p>
4145
</FadeIn>
4246
</div>
4347
</section>
@@ -62,6 +66,7 @@ export function BenchmarksContent() {
6266
<section className="section-padding pb-16">
6367
<div className="container-width">
6468
<FadeIn>
69+
<h2 className="text-xl font-semibold text-white mb-4">Parse Benchmarks</h2>
6570
<GlassCard className="p-0 overflow-hidden" hover={false}>
6671
<div className="overflow-x-auto">
6772
<table className="w-full text-sm text-left">
@@ -89,6 +94,7 @@ export function BenchmarksContent() {
8994
</table>
9095
</div>
9196
</GlassCard>
97+
<p className="text-xs text-zinc-500 mt-2 md:hidden">&larr; Swipe to see all columns &rarr;</p>
9298
</FadeIn>
9399
</div>
94100
</section>
@@ -111,38 +117,52 @@ export function BenchmarksContent() {
111117
</tr>
112118
</thead>
113119
<tbody>
114-
<tr className="border-b border-white/[0.04] hover:bg-white/[0.03] transition-colors">
115-
<td className="px-6 py-4 text-white font-medium">GoSQLX</td>
120+
<tr className="border-b border-white/[0.04] transition-colors bg-indigo-500/5 border-l-2 border-l-indigo-500">
121+
<td className="px-6 py-4 text-white font-medium">
122+
GoSQLX{' '}
123+
<span className="ml-2 inline-block rounded-full bg-indigo-500/20 px-2 py-0.5 text-xs font-medium text-indigo-300">
124+
This Library
125+
</span>
126+
</td>
116127
<td className="px-6 py-4 text-zinc-400">Go</td>
117128
<td className="px-6 py-4 text-zinc-300 font-mono">1.38M+</td>
118129
<td className="px-6 py-4 text-zinc-300">Low</td>
119-
<td className="px-6 py-4 text-accent-green font-medium"></td>
130+
<td className="px-6 py-4 text-accent-green font-medium">
131+
<span aria-label="Yes"></span>
132+
</td>
120133
</tr>
121134
<tr className="border-b border-white/[0.04] hover:bg-white/[0.03] transition-colors">
122135
<td className="px-6 py-4 text-zinc-300 font-medium">xwb1989/sqlparser</td>
123136
<td className="px-6 py-4 text-zinc-400">Go</td>
124137
<td className="px-6 py-4 text-zinc-400 font-mono">~380K</td>
125138
<td className="px-6 py-4 text-zinc-400">Higher</td>
126-
<td className="px-6 py-4 text-zinc-500"></td>
139+
<td className="px-6 py-4 text-zinc-500">
140+
<span aria-label="No"></span>
141+
</td>
127142
</tr>
128143
<tr className="border-b border-white/[0.04] hover:bg-white/[0.03] transition-colors">
129144
<td className="px-6 py-4 text-zinc-300 font-medium">pg_query_go</td>
130145
<td className="px-6 py-4 text-zinc-400">Go</td>
131146
<td className="px-6 py-4 text-zinc-400 font-mono">~220K</td>
132147
<td className="px-6 py-4 text-zinc-400">Higher (CGo)</td>
133-
<td className="px-6 py-4 text-zinc-500"></td>
148+
<td className="px-6 py-4 text-zinc-500">
149+
<span aria-label="No"></span>
150+
</td>
134151
</tr>
135152
<tr className="border-b border-white/[0.04] hover:bg-white/[0.03] transition-colors">
136153
<td className="px-6 py-4 text-zinc-300 font-medium">blastrain/sqlparser</td>
137154
<td className="px-6 py-4 text-zinc-400">Go</td>
138155
<td className="px-6 py-4 text-zinc-400 font-mono">~290K</td>
139156
<td className="px-6 py-4 text-zinc-400">Medium</td>
140-
<td className="px-6 py-4 text-zinc-500"></td>
157+
<td className="px-6 py-4 text-zinc-500">
158+
<span aria-label="No"></span>
159+
</td>
141160
</tr>
142161
</tbody>
143162
</table>
144163
</div>
145164
</GlassCard>
165+
<p className="text-xs text-zinc-500 mt-2 md:hidden">&larr; Swipe to see all columns &rarr;</p>
146166
</FadeIn>
147167
</div>
148168
</section>
@@ -155,14 +175,39 @@ export function BenchmarksContent() {
155175
<ul className="space-y-3">
156176
{methodology.map((item) => (
157177
<li key={item} className="flex items-start gap-3 text-sm text-zinc-400">
158-
<span className="mt-1.5 block h-1.5 w-1.5 rounded-full bg-zinc-600 shrink-0" />
178+
<span className="mt-1.5 block h-1.5 w-1.5 rounded-full bg-zinc-400 shrink-0" />
159179
{item}
160180
</li>
161181
))}
162182
</ul>
163183
</FadeIn>
164184
</div>
165185
</section>
186+
187+
{/* CTA */}
188+
<section className="section-padding pb-24">
189+
<div className="container-width">
190+
<FadeIn>
191+
<div className="mt-16 text-center">
192+
<p className="text-zinc-400 mb-4">Ready to use GoSQLX in your project?</p>
193+
<div className="flex gap-3 justify-center">
194+
<Link
195+
href="/docs/getting-started"
196+
className="inline-flex items-center rounded-lg bg-indigo-600 px-5 py-2.5 text-sm font-medium text-white hover:bg-indigo-500 transition-colors"
197+
>
198+
Get Started
199+
</Link>
200+
<Link
201+
href="/playground"
202+
className="inline-flex items-center rounded-lg border border-white/10 bg-white/5 px-5 py-2.5 text-sm font-medium text-zinc-300 hover:bg-white/10 hover:text-white transition-colors"
203+
>
204+
Try Playground
205+
</Link>
206+
</div>
207+
</div>
208+
</FadeIn>
209+
</div>
210+
</section>
166211
</main>
167212
);
168213
}

website/src/app/benchmarks/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import type { Metadata } from 'next';
22
import { BenchmarksContent } from './BenchmarksContent';
33

44
export const metadata: Metadata = {
5-
title: 'Benchmarks',
5+
title: 'GoSQLX Performance Benchmarks — 1.38M+ ops/sec SQL Parsing for Go',
66
description:
7-
'GoSQLX performance benchmarks. 1.38M+ ops/sec sustained, 8M+ tokens/sec throughput, validated across 20K+ concurrent operations.',
7+
'Detailed performance benchmarks for GoSQLX: 1.38M+ ops/sec sustained throughput, 8M+ tokens/sec, zero race conditions across 20K+ concurrent operations. Compare against xwb1989/sqlparser, pg_query_go, and blastrain/sqlparser.',
88
};
99

1010
export default function BenchmarksPage() {

website/src/app/docs/[...slug]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ export default async function DocPage({ params }: PageProps) {
152152
</main>
153153

154154
{/* Table of Contents */}
155-
<div className="hidden xl:block w-48 shrink-0 py-10 pr-6">
155+
<div className="hidden xl:block w-56 shrink-0 py-10 pr-6">
156156
<Toc headings={headings} />
157157
</div>
158158
</div>

website/src/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export default function RootLayout({
8383
}}
8484
/>
8585
<Navbar />
86-
<main id="main-content" className="pt-16">{children}</main>
86+
<div id="main-content" className="pt-16">{children}</div>
8787
<Footer />
8888
<ServiceWorkerRegister />
8989
</body>

website/src/components/home/Hero.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const SAMPLE_AST = `{
4747

4848
export function Hero() {
4949
return (
50-
<section className="relative min-h-screen flex items-center justify-center">
50+
<section className="relative min-h-screen flex items-center justify-center overflow-hidden">
5151
{/* Background gradient mesh */}
5252
<div className="absolute inset-0 pointer-events-none overflow-hidden" aria-hidden="true">
5353
{/* Top-right indigo glow */}
@@ -89,7 +89,7 @@ export function Hero() {
8989
{/* Headline */}
9090
<FadeIn delay={0.1}>
9191
<h1
92-
className="text-3xl sm:text-5xl md:text-6xl lg:text-7xl font-bold mb-6 break-words hyphens-auto"
92+
className="text-3xl sm:text-5xl md:text-6xl lg:text-7xl font-bold mb-6 break-words hyphens-auto w-full max-w-full px-4 sm:px-0"
9393
style={{ letterSpacing: '-0.03em' }}
9494
>
9595
<GradientText>Parse SQL at the speed of Go</GradientText>
@@ -165,7 +165,7 @@ export function Hero() {
165165
<div className="mt-6">
166166
<Link
167167
href="/playground"
168-
className="text-sm text-zinc-300 hover:text-zinc-300 transition-colors inline-flex items-center gap-1.5"
168+
className="text-sm text-zinc-300 hover:text-white transition-colors inline-flex items-center gap-1.5"
169169
>
170170
Open Full Playground
171171
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">

website/src/components/home/McpSection.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22

3+
import Link from 'next/link';
34
import { FadeIn } from '@/components/ui/FadeIn';
45
import { TerminalMockup } from '@/components/ui/TerminalMockup';
56

@@ -36,13 +37,23 @@ export function McpSection() {
3637
{tools.map((tool) => (
3738
<span
3839
key={tool}
39-
className="text-xs font-mono text-zinc-500 bg-white/[0.03] border border-white/[0.06] rounded-md px-2.5 py-1"
40+
className="text-xs font-mono text-zinc-300 bg-white/[0.03] border border-white/[0.06] rounded-md px-2.5 py-1"
4041
>
4142
{tool}
4243
</span>
4344
))}
4445
</div>
4546
</FadeIn>
47+
<FadeIn delay={0.35}>
48+
<div className="mt-8">
49+
<Link
50+
href="/docs/mcp-guide"
51+
className="text-sm text-accent-indigo hover:underline inline-flex items-center gap-1"
52+
>
53+
Learn more →
54+
</Link>
55+
</div>
56+
</FadeIn>
4657
</div>
4758
</section>
4859
);

website/src/components/home/StatsBar.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { FadeIn } from '@/components/ui/FadeIn';
55
import { AnimatedCounter } from '@/components/ui/AnimatedCounter';
66

77
const stats = [
8-
{ value: 1250000, suffix: '+', label: 'ops/sec', color: 'text-accent-orange' },
8+
{ value: 1380000, suffix: '+', label: 'ops/sec', color: 'text-accent-orange' },
99
{ value: 1, suffix: 'μs', label: 'latency', color: 'text-accent-indigo', prefix: '<' },
1010
{ value: 85, suffix: '%', label: 'SQL-99', color: 'text-accent-green' },
1111
{ value: 6, suffix: '', label: 'Dialects', color: 'text-accent-purple' },
@@ -15,7 +15,7 @@ export function StatsBar() {
1515
return (
1616
<section className="py-20">
1717
<div className="max-w-6xl mx-auto px-4">
18-
<div className="flex flex-wrap justify-center gap-4 md:gap-8">
18+
<div className="grid grid-cols-2 sm:grid-cols-4 gap-4 md:gap-8 justify-items-center">
1919
{stats.map((stat, i) => (
2020
<FadeIn key={stat.label} delay={i * 0.1}>
2121
<GlassCard className="p-6 text-center min-w-[140px]">

website/src/components/playground/AnalyzeTab.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ function scoreRing(score: number): string {
4949
return "ring-red-500/30";
5050
}
5151

52-
function ScoreCard({ title, score, subtitle }: { title: string; score: number | string; subtitle?: string }) {
52+
function ScoreCard({ title, score, subtitle, subtitleTitle }: { title: string; score: number | string; subtitle?: string; subtitleTitle?: string }) {
5353
const numScore = typeof score === "number" ? score : NaN;
5454
const displayScore = typeof score === "string" ? score : String(score);
5555
const isNumeric = !isNaN(numScore);
@@ -62,7 +62,7 @@ function ScoreCard({ title, score, subtitle }: { title: string; score: number |
6262
>
6363
{displayScore}
6464
</div>
65-
{subtitle && <div className="text-xs text-slate-400 mt-1">{subtitle}</div>}
65+
{subtitle && <div className="text-xs text-slate-400 mt-1" title={subtitleTitle}>{subtitle}</div>}
6666
</div>
6767
);
6868
}
@@ -126,7 +126,8 @@ export default function AnalyzeTab({ data }: AnalyzeTabProps) {
126126
<ScoreCard
127127
title="Security"
128128
score={securityScore}
129-
subtitle={`${critical}C ${high}H ${medium}M ${low}L`}
129+
subtitle={`C:${critical} H:${high} M:${medium} L:${low}`}
130+
subtitleTitle="Critical / High / Medium / Low severity findings"
130131
/>
131132
<ScoreCard
132133
title="Optimization"
@@ -136,7 +137,7 @@ export default function AnalyzeTab({ data }: AnalyzeTabProps) {
136137
<ScoreCard
137138
title="Complexity"
138139
score={complexityLevel}
139-
subtitle="Query complexity"
140+
subtitle="simple → moderate → complex"
140141
/>
141142
</div>
142143

website/src/components/playground/FormatTab.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ export default function FormatTab({ data }: FormatTabProps) {
3333
const formatted = typeof data === "string" ? data : data.result || data.formatted || JSON.stringify(data, null, 2);
3434

3535
return (
36-
<div className="p-4 h-full overflow-auto">
36+
<div className="p-2 h-full overflow-hidden">
3737
<SqlEditor
3838
value={formatted}
3939
onChange={() => {}}
4040
readOnly={true}
41-
minHeight="300px"
41+
minHeight="200px"
4242
placeholder="Formatted SQL will appear here..."
4343
/>
4444
</div>

website/src/components/playground/Playground.tsx

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,25 +110,59 @@ export default function Playground() {
110110

111111
if (loading) {
112112
return (
113-
<div className="flex items-center justify-center h-full bg-[#09090b]">
114-
<div className="text-center space-y-4 max-w-xs">
115-
<div className="inline-block w-8 h-8 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" role="status" aria-label="Loading SQL parser" />
116-
<p className="text-slate-400 text-sm">
113+
<div className="flex flex-col h-full bg-[#09090b]" aria-busy="true" aria-label="Loading SQL parser">
114+
{/* Skeleton toolbar */}
115+
<div className="flex items-center justify-between px-4 py-2 border-b border-slate-800 bg-slate-900/50">
116+
<div className="flex items-center gap-3">
117+
<div className="animate-pulse bg-zinc-800 rounded h-4 w-28" />
118+
<div className="h-4 w-px bg-slate-700" />
119+
<div className="animate-pulse bg-zinc-800 rounded h-6 w-36" />
120+
</div>
121+
<div className="animate-pulse bg-zinc-800 rounded h-4 w-20" />
122+
</div>
123+
{/* Skeleton panels */}
124+
<div className="flex flex-col lg:flex-row flex-1 min-h-0">
125+
{/* Left: editor skeleton */}
126+
<div className="w-full lg:w-1/2 border-r border-slate-800 flex flex-col min-h-0 p-4 gap-3">
127+
<div className="animate-pulse bg-zinc-800 rounded h-3 w-3/4" />
128+
<div className="animate-pulse bg-zinc-800 rounded h-3 w-full" />
129+
<div className="animate-pulse bg-zinc-800 rounded h-3 w-5/6" />
130+
<div className="animate-pulse bg-zinc-800 rounded h-3 w-2/3" />
131+
<div className="animate-pulse bg-zinc-800 rounded h-3 w-4/5" />
132+
</div>
133+
{/* Right: tab + content skeleton */}
134+
<div className="w-full lg:w-1/2 flex flex-col min-h-0">
135+
<div className="flex border-b border-slate-800 bg-slate-900/30 gap-2 px-2 py-1">
136+
{[80, 72, 60, 88].map((w, i) => (
137+
<div key={i} className={`animate-pulse bg-zinc-800 rounded h-6`} style={{ width: w }} />
138+
))}
139+
</div>
140+
<div className="flex-1 p-4 flex flex-col gap-3">
141+
<div className="animate-pulse bg-zinc-800 rounded h-3 w-1/2" />
142+
<div className="animate-pulse bg-zinc-800 rounded h-3 w-3/4" />
143+
<div className="animate-pulse bg-zinc-800 rounded h-3 w-2/3" />
144+
</div>
145+
</div>
146+
</div>
147+
{/* Progress overlay at bottom */}
148+
<div className="px-4 py-2 border-t border-slate-800 bg-slate-900/50 flex items-center gap-3">
149+
<div className="inline-block w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin flex-shrink-0" role="status" />
150+
<p className="text-slate-400 text-xs">
117151
{progress < 1
118-
? `Downloading SQL parser... ${Math.round(progress * 100)}%`
119-
: "Initializing..."}
152+
? `Downloading SQL parser ${Math.round(progress * 100)}%`
153+
: "Initializing"}
120154
</p>
121155
{progress > 0 && progress < 1 && (
122156
<div
123-
className="w-full bg-slate-700 rounded-full h-1.5"
157+
className="flex-1 bg-slate-700 rounded-full h-1"
124158
role="progressbar"
125159
aria-valuenow={Math.round(progress * 100)}
126160
aria-valuemin={0}
127161
aria-valuemax={100}
128162
aria-label="Download progress"
129163
>
130164
<div
131-
className="bg-blue-500 h-1.5 rounded-full transition-all duration-300"
165+
className="bg-blue-500 h-1 rounded-full transition-all duration-300"
132166
style={{ width: `${progress * 100}%` }}
133167
/>
134168
</div>
@@ -190,12 +224,12 @@ export default function Playground() {
190224
<div className="px-4 py-2 border-b border-slate-800 bg-slate-900/30">
191225
<span className="text-xs text-slate-400 uppercase tracking-wider font-medium">Input</span>
192226
</div>
193-
<div className="flex-1 overflow-auto p-2">
227+
<div className="flex-1 overflow-hidden p-2">
194228
<SqlEditor
195229
value={sql}
196230
onChange={handleSqlChange}
197231
placeholder="Enter your SQL query here..."
198-
minHeight="100%"
232+
minHeight="200px"
199233
/>
200234
</div>
201235
</div>

0 commit comments

Comments
 (0)