Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "libredb-studio-website",
"type": "module",
"version": "0.7.0",
"version": "0.7.1",
"scripts": {
"dev": "astro dev",
"build": "node scripts/sync-docker-compose.mjs && astro build",
Expand Down
Binary file added public/video/connect-poster.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions src/components/sections/CompareSection.astro
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,19 @@ const exportRows = rows.map((r) => ({
))
}
</div>

<p class="mt-6 text-[13px] leading-relaxed">
<span class="sql-com">
-- methodology: scored by the LibreDB team from each tool's public docs and pricing pages (last check:
2026-07-15). spotted an error?
</span>
<a
href="https://github.com/libredb/libredb-studio/issues"
target="_blank"
rel="noopener noreferrer"
class="text-muted hover:text-fg">file an issue →</a
>
</p>
</div>
<script
type="application/json"
Expand Down
8 changes: 8 additions & 0 deletions src/components/sections/FaqSection.astro
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ const faqs: QA[] = [
q: 'How does it compare to pgAdmin or DBeaver?',
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.',
},
{
q: 'How is LibreDB Platform licensed?',
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.',
},
{
q: 'Why sponsor LibreDB?',
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.',
},
];
---

Expand Down
17 changes: 17 additions & 0 deletions src/components/sections/FeaturesSection.astro
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,23 @@ const features: Feature[] = [
))
}
</div>

<!-- Closing CTA — long result sets shouldn't end in a dead end -->
<section class="mt-10 flex flex-wrap gap-3">
<a
href="https://app.libredb.org"
target="_blank"
rel="noopener noreferrer"
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"
>
<span aria-hidden="true">▶</span> Try them live
</a>
<a
href="/get-started"
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"
>Get started <span aria-hidden="true">→</span></a
>
</section>
</div>
<script
type="application/json"
Expand Down
48 changes: 48 additions & 0 deletions src/components/sections/GetStartedSection.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
---
import SectionHeader from './SectionHeader.astro';
import PromoVideo from './PromoVideo.astro';
import { ENGINES } from '../../data/engines';

const engineList = `${ENGINES.slice(0, -1).join(', ')}, or ${ENGINES.at(-1)}`;

interface Line {
kind: 'cmd' | 'comment' | 'out';
Expand Down Expand Up @@ -55,6 +59,18 @@ const copyText = (s: Step) =>
<div class="mx-auto max-w-6xl">
<SectionHeader title="Get started in minutes" subtitle="Up and running with three simple steps." />

<!-- The whole journey in motion, before the steps (click-to-load facade) -->
<div class="mb-8 max-w-3xl">
<PromoVideo
videoId="KazHTclbiSQ"
title="Connect Your Own Database in LibreDB Studio"
poster="/video/connect-poster.jpg"
/>
<p class="mt-2 text-[13px] leading-relaxed">
<span class="sql-com">-- 70s: install → connect your database → first query. the steps below, in motion.</span>
</p>
</div>

<div class="grid grid-cols-1 gap-4 lg:grid-cols-3">
{
steps.map((s) => (
Expand Down Expand Up @@ -141,6 +157,38 @@ const copyText = (s: Step) =>
<a href="/deploy" class="text-[13px] text-primary hover:underline">Explore all deploy options →</a>
</div>
</div>

<!-- The first real step AFTER the app is running -->
<section class="mt-10 border border-edge bg-panel p-6">
<h3 class="text-[15px] font-semibold text-bright">Next: connect your first database</h3>
<ol class="mt-4 flex list-none flex-col gap-3 text-[13px] leading-relaxed text-muted">
<li>
<span class="text-faint select-none">1&nbsp;</span> Log in and open{' '}
<span class="font-semibold text-fg">Connections → New connection</span>.
</li>
<li><span class="text-faint select-none">2&nbsp;</span> Pick your engine — {engineList}.</li>
<li>
<span class="text-faint select-none">3&nbsp;</span> Enter host and credentials.{' '}
<span class="text-dim">Start with a dedicated read-only database account</span> — least privilege first, write access
when you actually need it. Databases behind a firewall connect over an SSH tunnel.
</li>
<li>
<span class="text-faint select-none">4&nbsp;</span> Deploying for a team? Define{' '}
<span class="font-semibold text-fg">seed connections</span> whose credentials resolve from environment variables at
runtime — secrets stay in your secret manager, never in a config file.
</li>
</ol>

<div class="mt-5 flex flex-wrap gap-4 text-[13px]">
<a
href="https://github.com/libredb/libredb-studio/blob/main/docs/SEED_CONNECTIONS.md"
target="_blank"
rel="noopener noreferrer"
class="text-primary hover:underline">Seed connections guide →</a
>
<a href="/security" class="text-primary hover:underline">How credentials are handled →</a>
</div>
</section>
</div>
<script
type="application/json"
Expand Down
36 changes: 34 additions & 2 deletions src/components/sections/HomeSection.astro
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
---
import PromoVideo from './PromoVideo.astro';
import { ENGINES } from '../../data/engines';
import { sectionById } from '../../data/sections';

const DEMO = 'https://app.libredb.org';

const databases = ['PostgreSQL', 'MySQL', 'Oracle', 'SQL Server', 'SQLite', 'MongoDB', 'Redis'];
const databases = ENGINES;
const featureRows = sectionById['features'].rows;

// Info-scent bridge to /features: four flagship rows of the full result set.
const flagship = [
{ name: 'NL2SQL Copilot', line: 'Plain English in, executable SQL out.' },
{ name: 'AI Query Safety', line: 'Risk analysis before destructive queries run.' },
{ name: 'Visual EXPLAIN', line: 'Graphical plans with plain-language notes.' },
{ name: 'Data Masking', line: 'Sensitive columns masked in grid and exports.' },
];
---

<div class="mx-auto max-w-5xl px-1">
Expand Down Expand Up @@ -62,6 +73,27 @@ const databases = ['PostgreSQL', 'MySQL', 'Oracle', 'SQL Server', 'SQLite', 'Mon
</p>
</div>

<!-- Feature bridge: a taste of the result set behind /features -->
<div class="mt-12 border-t border-edge pt-8">
<p class="text-[13px]">
<span class="sql-kw">SELECT</span> name, summary <span class="sql-kw">FROM</span> features{' '}
<span class="sql-kw">LIMIT</span>{' '}<span class="sql-num">4</span>;
</p>
<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">
{
flagship.map((f) => (
<div class="bg-panel p-4">
<h3 class="text-[13px] font-semibold text-bright">{f.name}</h3>
<p class="mt-1.5 text-[12px] leading-relaxed text-dim">{f.line}</p>
</div>
))
}
</div>
<a href="/features" class="mt-3 inline-block text-[13px] text-muted hover:text-fg">
… {featureRows - flagship.length} more rows — see all {featureRows} features <span aria-hidden="true">→</span>
</a>
</div>

<!-- The LibreDB family / open-core (secondary; Studio stays the hero above) -->
<div class="mt-14 border-t border-edge pt-8">
<p class="text-[11px] tracking-wider text-faint uppercase">The LibreDB family — one core, three products</p>
Expand Down Expand Up @@ -90,7 +122,7 @@ const databases = ['PostgreSQL', 'MySQL', 'Oracle', 'SQL Server', 'SQLite', 'Mon
<span class="text-[11px] text-dim">beta</span>
</div>
<p class="mt-2 text-[12px] leading-relaxed text-dim">
Managed for teams — Database Access Governance: authorized, audited, multi-tenant.
Self-hosted for enterprises — Database Access Governance: authorized, audited, multi-tenant.
</p>
</a>
</div>
Expand Down
36 changes: 31 additions & 5 deletions src/components/sections/PlatformSection.astro
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ const capabilities = [
name: 'Query audit log',
detail: 'Every query logged with user, timing, and status — full accountability.',
},
{ name: 'Plans', detail: 'Free, Team, Business, and Enterprise tiers — runtime-configurable.' },
{
name: 'Enterprise licensing',
detail:
'Self-hosted, per-organization licenses during beta — tiers are runtime-configurable per license. No online sales yet.',
},
{
name: 'SSO / OIDC',
detail: 'Vendor-agnostic single sign-on (Auth0, Keycloak, Okta, Azure AD).',
Expand All @@ -29,8 +33,10 @@ const capabilities = [

const openCore = [
{ tier: 'Studio', line: 'OSS · free · self-hosted · community', cls: 'text-primary' },
{ tier: 'Platform', line: 'closed · paid · cloud · enterprise', cls: 'text-ai' },
{ tier: 'Platform', line: 'closed source · beta · self-hosted · enterprise license', cls: 'text-ai' },
];

const LINKEDIN = 'https://www.linkedin.com/company/libredb';
---

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

<!-- Problem callout -->
Expand Down Expand Up @@ -79,7 +86,7 @@ const openCore = [
<div class="mt-10">
<SectionHeader
title="Open core"
subtitle="Studio is free & open; Platform is the managed layer that funds the open-source work."
subtitle="Studio is free & open; Platform is the commercial layer that funds the open-source work."
/>
<div class="grid grid-cols-1 gap-px overflow-hidden border border-edge bg-edge sm:grid-cols-2">
{
Expand All @@ -98,9 +105,28 @@ const openCore = [
</p>
</div>

<!-- How to get it: honest licensing model, with a human contact path -->
<div class="mt-10 border-l-2 border-ai/60 bg-panel p-5">
<h3 class="text-[15px] font-semibold text-bright">How Platform is sold today</h3>
<p class="mt-2 max-w-2xl text-[13.5px] leading-relaxed text-dim">
Platform is in beta and is licensed <span class="text-fg"
>per organization, self-hosted on your infrastructure</span
> — there is no online purchase or hosted subscription yet. Licensing conversations happen directly with the team, and
beta partners shape the roadmap.
</p>
<a
href={LINKEDIN}
target="_blank"
rel="noopener noreferrer"
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"
>
Talk to us about licensing <span aria-hidden="true">→</span>
</a>
</div>

<!-- CTA (the only external link) -->
<div
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"
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"
>
<div>
<h3 class="text-[16px] font-bold text-bright">Try the beta</h3>
Expand Down
110 changes: 110 additions & 0 deletions src/components/sections/SecuritySection.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
// The consolidated security page a DBA or security reviewer looks for before
// letting a tool near production. Deliberately honest: it states what is
// enforced where (and display-level vs server-side), never more.
import SectionHeader from './SectionHeader.astro';

const SECURITY_MD = 'https://github.com/libredb/libredb-studio/blob/main/SECURITY.md';
const SEED_DOCS = 'https://github.com/libredb/libredb-studio/blob/main/docs/SEED_CONNECTIONS.md';
const OIDC_DOCS = 'https://github.com/libredb/libredb-studio/blob/main/docs/OIDC.md';

const controls = [
{
control: 'Authentication',
detail:
'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.',
href: OIDC_DOCS,
linkLabel: 'OIDC guide',
},
{
control: 'Authorization',
detail:
'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.',
},
{
control: 'Database credentials',
detail:
'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).',
href: SEED_DOCS,
linkLabel: 'Seed connections',
},
{
control: 'Transport',
detail:
'TLS between browser and app; TLS and SSH tunnels from the app to your databases — including databases behind firewalls that never get public exposure.',
},
{
control: 'Data masking',
detail:
'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.',
},
{
control: 'Self-hosting & isolation',
detail:
'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.',
},
{
control: 'Supply chain',
detail:
'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.',
},
];
---

<div class="mx-auto max-w-5xl">
<SectionHeader
title="Security model"
subtitle="What is enforced, where it is enforced, and how to reach us when something isn't."
/>

<div class="flex flex-col gap-px overflow-hidden border border-edge bg-edge">
{
controls.map((c) => (
<article class="grid grid-cols-1 gap-2 bg-panel p-5 sm:grid-cols-[180px_1fr] sm:gap-6">
<h3 class="text-[13px] font-semibold tracking-wide text-bright uppercase">{c.control}</h3>
<div>
<p class="text-[13px] leading-relaxed text-muted">{c.detail}</p>
{c.href && (
<a
href={c.href}
target="_blank"
rel="noopener noreferrer"
class="mt-1.5 inline-block text-[12px] text-primary hover:text-primary-bright"
>
{c.linkLabel} <span aria-hidden="true">→</span>
</a>
)}
</div>
</article>
))
}
</div>

<!-- Responsible disclosure -->
<section class="mt-10 border-l-2 border-warn/60 bg-panel p-5">
<h3 class="text-[15px] font-semibold text-bright">Found a vulnerability?</h3>
<p class="mt-2 max-w-2xl text-[13px] leading-relaxed text-dim">
Please report it privately — not in a public issue. The disclosure process, supported versions, and response
commitments live in the repository's security policy.
</p>
<a
href={SECURITY_MD}
target="_blank"
rel="noopener noreferrer"
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"
>
Read SECURITY.md <span aria-hidden="true">→</span>
</a>
</section>

<p class="mt-6 text-[13px] leading-relaxed">
<span class="sql-com">-- honest by default: if a control is display-level, this page says so.</span>
</p>
</div>
<script
type="application/json"
data-export-payload="security"
data-export-filename="security.json"
data-export-format="json"
set:html={JSON.stringify(controls.map(({ control, detail }) => ({ control, detail })))}
/>
Loading
Loading