Skip to content

Commit 40b543c

Browse files
cevhericlaude
andcommitted
feat: persona-driven trust & info-scent fixes across the site
Addresses the visitor-persona audit findings in one pass: First-time developer (info scent): - Homepage gains a feature bridge — an in-fiction "SELECT name, summary FROM features LIMIT 4;" mini result set (NL2SQL Copilot, AI Query Safety, Visual EXPLAIN, Data Masking) linking to all 18 features Evaluating DBA (consistency + trust): - New /security page consolidating the honest security model: OIDC+PKCE, RBAC, env-var seed credentials, TLS/SSH tunnels, display-level masking (stated as such), supply-chain checksums, and the SECURITY.md disclosure path - Studio version now fetched from GitHub releases at build time (bare-semver app tags only, chart releases filtered, memoized, with fallback) and rendered as "studio:x.y.z" in the StatusBar and as JSON-LD softwareVersion — replaces three conflicting hardcoded numbers - Engine list single-sourced in src/data/engines.ts (hero + JSON-LD) - Compare page gains a methodology footnote with last-check date and a corrections channel DevOps engineer: - /get-started gains "Next: connect your first database" — four steps with least-privilege guidance and links to the seed-connections guide and /security - /features ends with a closing CTA instead of a dead end Customer (honest licensing): - Platform pages now state the real model: closed source, beta, self-hosted, per-organization enterprise licenses, no online sales yet, with a "talk to us" contact path (LinkedIn) - Home family card: "Managed for teams" -> "Self-hosted for enterprises" - FAQ +2: "How is LibreDB Platform licensed?" and "Why sponsor LibreDB?" JSON-LD sameAs now includes X/YouTube/Instagram/Reddit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 2fdbcd6 commit 40b543c

14 files changed

Lines changed: 366 additions & 13 deletions

‎src/components/sections/CompareSection.astro‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,19 @@ const exportRows = rows.map((r) => ({
122122
))
123123
}
124124
</div>
125+
126+
<p class="mt-6 text-[13px] leading-relaxed">
127+
<span class="sql-com">
128+
-- methodology: scored by the LibreDB team from each tool's public docs and pricing pages (last check:
129+
2026-07-15). spotted an error?
130+
</span>
131+
<a
132+
href="https://github.com/libredb/libredb-studio/issues"
133+
target="_blank"
134+
rel="noopener noreferrer"
135+
class="text-muted hover:text-fg">file an issue →</a
136+
>
137+
</p>
125138
</div>
126139
<script
127140
type="application/json"

‎src/components/sections/FaqSection.astro‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ const faqs: QA[] = [
4545
q: 'How does it compare to pgAdmin or DBeaver?',
4646
a: 'Unlike pgAdmin (PostgreSQL only) or DBeaver (desktop app), LibreDB Studio is web-based, mobile-ready, and deeply AI-powered. Beyond NL2SQL, we offer AI Query Safety Analysis, AI Query Explainer, AI Query Autopilot, AI Data Profiler, ORM Code Generator, Test Data Generator, Interactive Pivot Tables, ER Diagrams, Database Documentation, and automatic Data Masking with RBAC enforcement - features no desktop IDE provides. Zero installation, works on any device.',
4747
},
48+
{
49+
q: 'How is LibreDB Platform licensed?',
50+
a: 'Platform is the closed-source enterprise layer of the open-core model, currently in beta. It is licensed per organization and self-hosted on your own infrastructure — there is no online purchase or hosted subscription yet. Licensing conversations happen directly with the team (reach us on LinkedIn), and Platform revenue funds the open-source work on Studio and the LibreDB engine. Studio itself stays MIT and free forever, regardless.',
51+
},
52+
{
53+
q: 'Why sponsor LibreDB?',
54+
a: 'Studio is MIT-licensed and free forever — no premium tier is coming to paywall it. Sponsorship (github.com/sponsors/libredb) directly funds what you already use: maintenance across seven database engines, security reviews, the release pipeline that ships Docker, Helm, npm, Homebrew and Snap packages on every release, and development of the open-source LibreDB engine. If Studio saves your team an hour a month, a sponsorship is the cheapest way to keep it alive and independent.',
55+
},
4856
];
4957
---
5058

‎src/components/sections/FeaturesSection.astro‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,23 @@ const features: Feature[] = [
135135
))
136136
}
137137
</div>
138+
139+
<!-- Closing CTA — long result sets shouldn't end in a dead end -->
140+
<section class="mt-10 flex flex-wrap gap-3">
141+
<a
142+
href="https://app.libredb.org"
143+
target="_blank"
144+
rel="noopener noreferrer"
145+
class="inline-flex items-center gap-2 rounded-md bg-primary px-5 py-2.5 text-sm font-medium text-white transition-colors hover:bg-primary-bright"
146+
>
147+
<span aria-hidden="true">▶</span> Try them live
148+
</a>
149+
<a
150+
href="/get-started"
151+
class="inline-flex items-center gap-2 rounded-md border border-edge-strong px-5 py-2.5 text-sm font-medium text-fg transition-colors hover:bg-raised"
152+
>Get started <span aria-hidden="true">→</span></a
153+
>
154+
</section>
138155
</div>
139156
<script
140157
type="application/json"

‎src/components/sections/GetStartedSection.astro‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,40 @@ const copyText = (s: Step) =>
141141
<a href="/deploy" class="text-[13px] text-primary hover:underline">Explore all deploy options →</a>
142142
</div>
143143
</div>
144+
145+
<!-- The first real step AFTER the app is running -->
146+
<section class="mt-10 border border-edge bg-panel p-6">
147+
<h3 class="text-[15px] font-semibold text-bright">Next: connect your first database</h3>
148+
<ol class="mt-4 flex list-none flex-col gap-3 text-[13px] leading-relaxed text-muted">
149+
<li>
150+
<span class="text-faint select-none">1&nbsp;</span> Log in and open
151+
<span class="font-semibold text-fg">Connections → New connection</span>.
152+
</li>
153+
<li>
154+
<span class="text-faint select-none">2&nbsp;</span> Pick your engine — PostgreSQL, MySQL, Oracle, SQL Server, SQLite,
155+
MongoDB, or Redis.
156+
</li>
157+
<li>
158+
<span class="text-faint select-none">3&nbsp;</span> Enter host and credentials.
159+
<span class="text-dim">Start with a dedicated read-only database account</span> — least privilege first, write access
160+
when you actually need it. Databases behind a firewall connect over an SSH tunnel.
161+
</li>
162+
<li>
163+
<span class="text-faint select-none">4&nbsp;</span> Deploying for a team? Define
164+
<span class="font-semibold text-fg">seed connections</span> whose credentials resolve from environment variables at
165+
runtime — secrets stay in your secret manager, never in a config file.
166+
</li>
167+
</ol>
168+
<div class="mt-5 flex flex-wrap gap-4 text-[13px]">
169+
<a
170+
href="https://github.com/libredb/libredb-studio/blob/main/docs/SEED_CONNECTIONS.md"
171+
target="_blank"
172+
rel="noopener noreferrer"
173+
class="text-primary hover:underline">Seed connections guide →</a
174+
>
175+
<a href="/security" class="text-primary hover:underline">How credentials are handled →</a>
176+
</div>
177+
</section>
144178
</div>
145179
<script
146180
type="application/json"

‎src/components/sections/HomeSection.astro‎

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
---
22
import PromoVideo from './PromoVideo.astro';
3+
import { ENGINES } from '../../data/engines';
34
45
const DEMO = 'https://app.libredb.org';
56
6-
const databases = ['PostgreSQL', 'MySQL', 'Oracle', 'SQL Server', 'SQLite', 'MongoDB', 'Redis'];
7+
const databases = ENGINES;
8+
9+
// Info-scent bridge to /features: four flagship rows of the full result set.
10+
const flagship = [
11+
{ name: 'NL2SQL Copilot', line: 'Plain English in, executable SQL out.' },
12+
{ name: 'AI Query Safety', line: 'Risk analysis before destructive queries run.' },
13+
{ name: 'Visual EXPLAIN', line: 'Graphical plans with plain-language notes.' },
14+
{ name: 'Data Masking', line: 'Sensitive columns masked in grid and exports.' },
15+
];
716
---
817

918
<div class="mx-auto max-w-5xl px-1">
@@ -62,6 +71,27 @@ const databases = ['PostgreSQL', 'MySQL', 'Oracle', 'SQL Server', 'SQLite', 'Mon
6271
</p>
6372
</div>
6473

74+
<!-- Feature bridge: a taste of the result set behind /features -->
75+
<div class="mt-12 border-t border-edge pt-8">
76+
<p class="text-[13px]">
77+
<span class="sql-kw">SELECT</span> name, summary <span class="sql-kw">FROM</span> features{' '}
78+
<span class="sql-kw">LIMIT</span>{' '}<span class="sql-num">4</span>;
79+
</p>
80+
<div class="mt-4 grid grid-cols-1 gap-px overflow-hidden border border-edge bg-edge sm:grid-cols-2 lg:grid-cols-4">
81+
{
82+
flagship.map((f) => (
83+
<div class="bg-panel p-4">
84+
<h3 class="text-[13px] font-semibold text-bright">{f.name}</h3>
85+
<p class="mt-1.5 text-[12px] leading-relaxed text-dim">{f.line}</p>
86+
</div>
87+
))
88+
}
89+
</div>
90+
<a href="/features" class="mt-3 inline-block text-[13px] text-muted hover:text-fg">
91+
… 14 more rows — see all 18 features <span aria-hidden="true">→</span>
92+
</a>
93+
</div>
94+
6595
<!-- The LibreDB family / open-core (secondary; Studio stays the hero above) -->
6696
<div class="mt-14 border-t border-edge pt-8">
6797
<p class="text-[11px] tracking-wider text-faint uppercase">The LibreDB family — one core, three products</p>
@@ -90,7 +120,7 @@ const databases = ['PostgreSQL', 'MySQL', 'Oracle', 'SQL Server', 'SQLite', 'Mon
90120
<span class="text-[11px] text-dim">beta</span>
91121
</div>
92122
<p class="mt-2 text-[12px] leading-relaxed text-dim">
93-
Managed for teams — Database Access Governance: authorized, audited, multi-tenant.
123+
Self-hosted for enterprises — Database Access Governance: authorized, audited, multi-tenant.
94124
</p>
95125
</a>
96126
</div>

‎src/components/sections/PlatformSection.astro‎

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ const capabilities = [
2020
name: 'Query audit log',
2121
detail: 'Every query logged with user, timing, and status — full accountability.',
2222
},
23-
{ name: 'Plans', detail: 'Free, Team, Business, and Enterprise tiers — runtime-configurable.' },
23+
{
24+
name: 'Enterprise licensing',
25+
detail:
26+
'Self-hosted, per-organization licenses during beta — tiers are runtime-configurable per license. No online sales yet.',
27+
},
2428
{
2529
name: 'SSO / OIDC',
2630
detail: 'Vendor-agnostic single sign-on (Auth0, Keycloak, Okta, Azure AD).',
@@ -29,8 +33,10 @@ const capabilities = [
2933
3034
const openCore = [
3135
{ tier: 'Studio', line: 'OSS · free · self-hosted · community', cls: 'text-primary' },
32-
{ tier: 'Platform', line: 'closed · paid · cloud · enterprise', cls: 'text-ai' },
36+
{ tier: 'Platform', line: 'closed source · beta · self-hosted · enterprise license', cls: 'text-ai' },
3337
];
38+
39+
const LINKEDIN = 'https://www.linkedin.com/company/libredb';
3440
---
3541

3642
<div class="mx-auto max-w-5xl">
@@ -45,7 +51,8 @@ const openCore = [
4551
<span class="text-ai">Governance</span> Platform
4652
</h1>
4753
<p class="mt-5 max-w-2xl text-[15px] leading-relaxed text-muted">
48-
Centralized, authorized, audited database access for teams and enterprises — the managed, team form of LibreDB.
54+
Centralized, authorized, audited database access for teams and enterprises — the governed, team form of LibreDB,
55+
self-hosted on your infrastructure.
4956
</p>
5057

5158
<!-- Problem callout -->
@@ -79,7 +86,7 @@ const openCore = [
7986
<div class="mt-10">
8087
<SectionHeader
8188
title="Open core"
82-
subtitle="Studio is free & open; Platform is the managed layer that funds the open-source work."
89+
subtitle="Studio is free & open; Platform is the commercial layer that funds the open-source work."
8390
/>
8491
<div class="grid grid-cols-1 gap-px overflow-hidden border border-edge bg-edge sm:grid-cols-2">
8592
{
@@ -98,9 +105,28 @@ const openCore = [
98105
</p>
99106
</div>
100107

108+
<!-- How to get it: honest licensing model, with a human contact path -->
109+
<div class="mt-10 border-l-2 border-ai/60 bg-panel p-5">
110+
<h3 class="text-[15px] font-semibold text-bright">How Platform is sold today</h3>
111+
<p class="mt-2 max-w-2xl text-[13.5px] leading-relaxed text-dim">
112+
Platform is in beta and is licensed <span class="text-fg"
113+
>per organization, self-hosted on your infrastructure</span
114+
> — there is no online purchase or hosted subscription yet. Licensing conversations happen directly with the team, and
115+
beta partners shape the roadmap.
116+
</p>
117+
<a
118+
href={LINKEDIN}
119+
target="_blank"
120+
rel="noopener noreferrer"
121+
class="mt-4 inline-flex items-center gap-2 rounded-md border border-edge-strong px-4 py-2 text-[13px] font-medium text-fg transition-colors hover:bg-raised"
122+
>
123+
Talk to us about licensing <span aria-hidden="true">→</span>
124+
</a>
125+
</div>
126+
101127
<!-- CTA (the only external link) -->
102128
<div
103-
class="mt-10 flex flex-col items-start justify-between gap-4 border border-edge bg-panel p-6 sm:flex-row sm:items-center"
129+
class="mt-8 flex flex-col items-start justify-between gap-4 border border-edge bg-panel p-6 sm:flex-row sm:items-center"
104130
>
105131
<div>
106132
<h3 class="text-[16px] font-bold text-bright">Try the beta</h3>
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
---
2+
// The consolidated security page a DBA or security reviewer looks for before
3+
// letting a tool near production. Deliberately honest: it states what is
4+
// enforced where (and display-level vs server-side), never more.
5+
import SectionHeader from './SectionHeader.astro';
6+
7+
const SECURITY_MD = 'https://github.com/libredb/libredb-studio/blob/main/SECURITY.md';
8+
const SEED_DOCS = 'https://github.com/libredb/libredb-studio/blob/main/docs/SEED_CONNECTIONS.md';
9+
const OIDC_DOCS = 'https://github.com/libredb/libredb-studio/blob/main/docs/OIDC.md';
10+
11+
const controls = [
12+
{
13+
control: 'Authentication',
14+
detail:
15+
'OpenID Connect SSO (Auth0, Keycloak, Okta, Azure AD or any OIDC provider) using Authorization Code Flow with PKCE. Sessions ride JWTs in httpOnly cookies — no tokens in localStorage.',
16+
href: OIDC_DOCS,
17+
linkLabel: 'OIDC guide',
18+
},
19+
{
20+
control: 'Authorization',
21+
detail:
22+
'Role-based access control with per-connection visibility scoping — a connection can be exposed to admins only, to users, or to everyone. Roles map from your identity provider claims.',
23+
},
24+
{
25+
control: 'Database credentials',
26+
detail:
27+
'Seed connections resolve ${ENV_VAR} placeholders at runtime, so secrets live in your environment or secret manager — never in a config file. Pair each connection with a dedicated least-privilege database account (read-only to start).',
28+
href: SEED_DOCS,
29+
linkLabel: 'Seed connections',
30+
},
31+
{
32+
control: 'Transport',
33+
detail:
34+
'TLS between browser and app; TLS and SSH tunnels from the app to your databases — including databases behind firewalls that never get public exposure.',
35+
},
36+
{
37+
control: 'Data masking',
38+
detail:
39+
'Sensitive columns (email, phone, SSN, financial data) are detected and masked across the grid, exports, and clipboard with RBAC enforcement. Masking is display-level — combine it with database-side grants for hard guarantees.',
40+
},
41+
{
42+
control: 'Self-hosting & isolation',
43+
detail:
44+
'Self-hosting is a first-class citizen: run it on your infrastructure, inside your network, behind your VPN. Nothing needs to leave your perimeter — including AI, which can run fully local via Ollama or LM Studio.',
45+
},
46+
{
47+
control: 'Supply chain',
48+
detail:
49+
'MIT-licensed source you can audit line by line. Every release ships SHA256 checksums; CI runs CodeQL and SonarCloud. Images are published to GHCR with immutable version tags.',
50+
},
51+
];
52+
---
53+
54+
<div class="mx-auto max-w-5xl">
55+
<SectionHeader
56+
title="Security model"
57+
subtitle="What is enforced, where it is enforced, and how to reach us when something isn't."
58+
/>
59+
60+
<div class="flex flex-col gap-px overflow-hidden border border-edge bg-edge">
61+
{
62+
controls.map((c) => (
63+
<article class="grid grid-cols-1 gap-2 bg-panel p-5 sm:grid-cols-[180px_1fr] sm:gap-6">
64+
<h3 class="text-[13px] font-semibold tracking-wide text-bright uppercase">{c.control}</h3>
65+
<div>
66+
<p class="text-[13px] leading-relaxed text-muted">{c.detail}</p>
67+
{c.href && (
68+
<a
69+
href={c.href}
70+
target="_blank"
71+
rel="noopener noreferrer"
72+
class="mt-1.5 inline-block text-[12px] text-primary hover:text-primary-bright"
73+
>
74+
{c.linkLabel} <span aria-hidden="true">→</span>
75+
</a>
76+
)}
77+
</div>
78+
</article>
79+
))
80+
}
81+
</div>
82+
83+
<!-- Responsible disclosure -->
84+
<section class="mt-10 border-l-2 border-warn/60 bg-panel p-5">
85+
<h3 class="text-[15px] font-semibold text-bright">Found a vulnerability?</h3>
86+
<p class="mt-2 max-w-2xl text-[13px] leading-relaxed text-dim">
87+
Please report it privately — not in a public issue. The disclosure process, supported versions, and response
88+
commitments live in the repository's security policy.
89+
</p>
90+
<a
91+
href={SECURITY_MD}
92+
target="_blank"
93+
rel="noopener noreferrer"
94+
class="mt-4 inline-flex items-center gap-2 rounded-md border border-edge-strong px-4 py-2 text-[13px] font-medium text-fg transition-colors hover:bg-raised"
95+
>
96+
Read SECURITY.md <span aria-hidden="true">→</span>
97+
</a>
98+
</section>
99+
100+
<p class="mt-6 text-[13px] leading-relaxed">
101+
<span class="sql-com">-- honest by default: if a control is display-level, this page says so.</span>
102+
</p>
103+
</div>
104+
<script
105+
type="application/json"
106+
data-export-payload="security"
107+
data-export-filename="security.json"
108+
data-export-format="json"
109+
set:html={JSON.stringify(controls.map(({ control, detail }) => ({ control, detail })))}
110+
/>

‎src/components/studio/StatusBar.astro‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
---
22
// Bottom status bar: one connection signal, the real footer links, and a
33
// single faint IDE identity cluster. Every datum here appears nowhere else.
4+
// The studio version is fetched from GitHub releases at build time so the
5+
// site never advertises a stale number.
6+
import { getStudioVersion } from '../../lib/studio-version';
7+
8+
const studioVersion = await getStudioVersion();
49
---
510

611
<footer
@@ -66,7 +71,7 @@
6671
<span>Ln 1, Col 1</span>
6772
<span>UTF-8</span>
6873
<span>SQL</span>
69-
<span><span aria-hidden="true">◆</span> v0.9.29</span>
74+
<span><span aria-hidden="true">◆</span> studio:{studioVersion}</span>
7075
</span>
7176
</div>
7277
</footer>

‎src/data/engines.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// Single source of truth for the supported engine list. Every surface that
2+
// names or counts the engines (hero subtitle, JSON-LD, SEO copy) must derive
3+
// from this array — the 7/5/4 count drift across surfaces is what this fixes.
4+
export const ENGINES = ['PostgreSQL', 'MySQL', 'Oracle', 'SQL Server', 'SQLite', 'MongoDB', 'Redis'] as const;

0 commit comments

Comments
 (0)