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
12 changes: 7 additions & 5 deletions src/components/sections/HomeSection.astro
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ const flagship = [

<!-- Headline -->
<h1 class="mt-6 text-4xl leading-[1.05] font-extrabold tracking-tight text-bright sm:text-5xl lg:text-6xl">
The Modern, <span class="text-primary">AI-Powered</span><br class="hidden sm:block" /> SQL IDE
The editor that deploys<br class="hidden sm:block" />{' '}
<span class="text-primary">next to your data</span>
</h1>

<!-- Subtitle: the seven engines read as SQL string literals — one hue, in-fiction.
Each hero element states one fact once: badge = license, H1 = AI/IDE,
subtitle = engines + SSO, CTAs = demo/deploy. -->
<!-- Subtitle: the engines read as SQL string literals — one hue, in-fiction.
The list is derived from ENGINES so the count cannot drift.
Each hero element states one fact once: badge = license, H1 = the claim,
subtitle = engines + where it runs, CTAs = demo/deploy. -->
<p class="mt-6 max-w-2xl text-[15px] leading-relaxed text-muted sm:text-base">
One editor for{' '}
{
Expand All @@ -44,7 +46,7 @@ const flagship = [
</>
))
}
— in your browser, with SSO built in.
— in your browser, in your cluster, or inside your own product.
</p>

<!-- CTAs -->
Expand Down
149 changes: 149 additions & 0 deletions src/components/sections/ManifestoSection.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
import SectionHeader from './SectionHeader.astro';

// The five consequences of the belief. Each is a row of the `manifesto` table
// in sections.ts (rows: 5) — keep the two in step if either changes.
const consequences = [
{
belief: 'It runs in a browser',
consequence:
'Because the data is not on your machine, and neither are your teammates. A tool that has to be installed is a tool that half the team never opens.',
},
{
belief: 'It reaches a phone',
consequence:
'Because the incident that needs a query does not wait for you to open a laptop. The same editor, the same connections, on the screen you already have with you.',
},
{
belief: 'It deploys like infrastructure',
consequence:
'A container, a Helm chart, an OpenShift operator, a one-click template on your platform. The way everything else that sits next to a database gets installed.',
},
{
belief: 'It embeds',
consequence:
'One npm package, inside your own product. The most useful place for a database editor is the thing that created the database in the first place.',
},
{
belief: 'It holds nothing back',
consequence:
'Single sign-on, ER diagrams, the AI assistant and the NoSQL engines all ship in the MIT build. There is no edition where the useful parts live.',
},
];
---

<div class="mx-auto max-w-5xl">
<!-- Licence badge: the same fact the home hero states, restated as the premise
this page argues from rather than as a feature. -->
<span
class="inline-flex items-center gap-2 rounded-full border border-ok/30 bg-ok-tint px-3 py-1 text-[12px] text-ok"
>
<span class="h-1.5 w-1.5 rounded-full bg-ok" aria-hidden="true"></span>
Open source · MIT · nothing held back
</span>

<!-- Hero -->
<h1 class="mt-6 text-3xl leading-[1.1] font-extrabold tracking-tight text-bright sm:text-4xl lg:text-5xl">
Databases moved to the cloud.<br class="hidden sm:block" />{' '}
Their editors <span class="text-primary">stayed on the laptop.</span>
</h1>
<p class="mt-5 max-w-2xl text-[15px] leading-relaxed text-muted">
<strong class="font-semibold text-fg">The tool goes to the data. Not the data to the tool.</strong>{' '}
Everything else about LibreDB Studio follows from that one line — including the licence.
</p>

<!-- The two scenes. This is the part of the story that is not derivable from
the feature list, so it leads. -->
<div class="mt-10">
<SectionHeader
title="How we got here"
subtitle="Two moments, roughly a hundred times each, until the pattern was impossible to miss."
/>
<div class="grid grid-cols-1 gap-px overflow-hidden border border-edge bg-edge sm:grid-cols-2">
<article class="flex flex-col bg-panel p-5">
<h3 class="text-[15px] font-bold text-primary">Forty seconds, then an afternoon</h3>
<p class="mt-2 text-[13px] leading-relaxed text-dim">
You create a Postgres on a managed platform. It is ready in forty seconds. Then you want to look inside it —
so you open a port to the internet, dig an SSH tunnel, or install a desktop client on every machine that needs
one. The database took forty seconds. The window into it takes the rest of the day.
</p>
</article>
<article class="flex flex-col bg-panel p-5">
<h3 class="text-[15px] font-bold text-primary">Now multiply it</h3>
<p class="mt-2 text-[13px] leading-relaxed text-dim">
The team runs Postgres for the application, Mongo for documents, Redis for the cache, ClickHouse for the
events. An engineer joins on Monday and spends their first days working out which data lives where, hunting
connection strings, waiting on access, and installing a different tool per engine.
</p>
</article>
</div>
</div>

<!-- What moved and what did not -->
<div class="mt-10 border-l-2 border-edge-strong bg-panel p-5">
<p class="text-[14px] leading-relaxed text-dim">
Databases moved. They live in Kubernetes now, on managed platforms, in a customer's VPC reached through a jump
host. The tools that read them did not move. They are still desktop applications: heavy, licensed per seat,
install-first, built on the assumption of one database, one laptop, and one person who never changes machines.
</p>
</div>

<!-- The consequences -->
<div class="mt-10">
<SectionHeader
title="What the belief forces"
subtitle="Take it seriously and it stops being a preference. It becomes a specification."
/>
<div class="grid grid-cols-1 gap-px overflow-hidden border border-edge bg-edge sm:grid-cols-2">
{
consequences.map((c) => (
<article class="flex flex-col bg-panel p-5">
<h3 class="text-[15px] font-bold text-primary">{c.belief}</h3>
<p class="mt-2 text-[13px] leading-relaxed text-dim">{c.consequence}</p>
</article>
))
}
</div>
</div>

<!-- The payoff: the licence as an engineering consequence, not a gesture. -->
<div class="mt-10 border-l-2 border-primary bg-panel p-5">
<p class="text-[15px] font-semibold text-bright">MIT is not generosity. It is a requirement of the architecture.</p>
<p class="mt-2 text-[13.5px] text-dim">
You cannot place a per-seat licensed, feature-gated tool into every environment you own. The moment single sign-on
costs extra, the tool stops being deployable by default.
</p>
</div>

<!-- Why the paid product does not contradict any of the above -->
<div class="mt-10 border border-edge bg-panel p-6">
<h3 class="text-[16px] font-bold text-bright">Then why is Platform paid?</h3>
<p class="mt-2 max-w-2xl text-[13.5px] leading-relaxed text-dim">
Because it is a service rather than an environment. LibreDB <strong class="text-fg">Studio</strong> is MIT because it
has to go everywhere. LibreDB <strong class="text-fg">Platform</strong> is hosting, tenancy, billing and support for
teams that would rather not run Studio themselves.
</p>
<p class="mt-3 max-w-2xl text-[13.5px] leading-relaxed text-dim">
The line holds under pressure, which is the point. The editor you deploy is free and stays free. No capability is
moved across that line to manufacture a reason to upgrade.
</p>
</div>

<!-- Bridge back to the product -->
<div class="mt-10 flex flex-col gap-3 sm:flex-row">
<a
href="https://app.libredb.org"
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center justify-center gap-2 rounded-md bg-primary px-6 py-3 text-[15px] font-semibold text-white transition-colors hover:bg-primary-bright"
>
See it running
</a>
<a
href="/get-started"
class="inline-flex items-center justify-center gap-2 rounded-md border border-edge-strong bg-panel px-6 py-3 text-[15px] font-semibold text-fg transition-colors hover:border-line hover:bg-raised"
>
Run it yourself <span aria-hidden="true">→</span>
</a>
</div>
</div>
13 changes: 12 additions & 1 deletion src/data/engines.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
// Single source of truth for the supported engine list. Every surface that
// names or counts the engines (hero subtitle, JSON-LD, SEO copy) must derive
// from this array — the 7/5/4 count drift across surfaces is what this fixes.
export const ENGINES = ['PostgreSQL', 'MySQL', 'Oracle', 'SQL Server', 'SQLite', 'MongoDB', 'Redis'] as const;
export const ENGINES = [
'PostgreSQL',
'MySQL',
'Oracle',
'SQL Server',
'SQLite',
'MongoDB',
'Redis',
'Couchbase',
'ClickHouse',
'Apache Druid',
] as const;
20 changes: 20 additions & 0 deletions src/data/sections.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@ test('support section exists at /support and names the platform columns', () =>
expect(s.columns.map((c) => c.name)).toEqual(['component', 'supported', 'validated']);
});

test('studio manifesto section exists at /manifesto and names the story columns', () => {
const m = sectionById['manifesto'];
expect(m).toBeDefined();
expect(m.slug).toBe('manifesto');
expect(m.table).toBe('manifesto');
expect(m.schema).toBe('studio');
// The page renders one card per consequence of the belief; renaming a column
// silently breaks the parity with docs/BRAND_MESSAGING.md in libredb-studio.
expect(m.columns.map((c) => c.name)).toEqual(['belief', 'consequence']);
});

test('no section copy hardcodes an engine count', () => {
// engines.ts is the single source of truth precisely so counts cannot drift.
// Copy that spells out "7+ engines" goes stale the moment a provider lands.
for (const s of sections) {
expect(s.explain).not.toMatch(/\d\s*\+?\s*(engines|databases)/i);
expect(s.pageDescription).not.toMatch(/\d\s*\+?\s*(engines|databases)/i);
}
});

test('every section has page SEO fields', () => {
for (const s of sections) {
expect(typeof s.slug).toBe('string');
Expand Down
30 changes: 25 additions & 5 deletions src/data/sections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,30 @@ export const sections: SectionMeta[] = [
{ name: 'stats', type: 'JSONB' },
],
explain:
'Returns the LibreDB Studio overview: a modern, AI-powered, browser-based SQL IDE with SSO across 7+ engines — free and open source under MIT.',
'Returns the LibreDB Studio overview: the database editor that deploys next to your data instead of onto your laptop, with SSO and audit across ten engines — free and open source under MIT.',
slug: '',
pageTitle: 'LibreDB Studio - AI-Powered Open-Source SQL IDE',
pageDescription: 'LibreDB Studio - The Modern, AI-Powered Open-Source SQL IDE for Cloud-Native Teams',
pageTitle: 'LibreDB Studio - The Open-Source SQL IDE That Deploys Next to Your Data',
pageDescription:
'LibreDB Studio is the database editor that deploys next to your data instead of onto your laptop. Ten engines in one browser tab, with SSO and audit built in. Open source under MIT.',
schema: 'studio',
},
{
id: 'manifesto',
table: 'manifesto',
query: 'SELECT belief, consequence FROM manifesto;',
rows: 5,
cols: 2,
execMs: 2,
columns: [
{ name: 'belief', type: 'TEXT' },
{ name: 'consequence', type: 'TEXT' },
],
explain:
'Why LibreDB Studio exists: databases moved to the cloud and their editors stayed on the laptop. The tool goes to the data — which forces it to be browser-based, deployable, embeddable and unrestricted.',
slug: 'manifesto',
pageTitle: 'Why LibreDB Studio exists - the tool goes to the data',
pageDescription:
'Databases moved to the cloud. The tools that read them stayed on the laptop. LibreDB Studio deploys next to the data instead — which is why it is browser-based, deployable, embeddable, and MIT licensed with nothing held back.',
schema: 'studio',
},
{
Expand All @@ -63,7 +83,7 @@ export const sections: SectionMeta[] = [
slug: 'features',
pageTitle: 'Features — LibreDB Studio SQL IDE',
pageDescription:
'Everything you need to master your data: Monaco SQL editor, NL2SQL Copilot, AI query safety, 7+ databases, pro data grid, visual EXPLAIN, ER diagrams, data masking, SSO and more.',
'Everything you need to master your data: Monaco SQL editor, NL2SQL Copilot, AI query safety, ten database engines, pro data grid, visual EXPLAIN, ER diagrams, data masking, SSO and more.',
schema: 'studio',
},
{
Expand All @@ -79,7 +99,7 @@ export const sections: SectionMeta[] = [
{ name: 'driver', type: 'VARCHAR' },
],
explain:
'The database engines LibreDB Studio connects to — PostgreSQL, MySQL, Oracle, SQL Server, SQLite, MongoDB, Redis — behind one unified interface, plus LibreDB, our own embedded engine.',
'The database engines LibreDB Studio connects to — PostgreSQL, MySQL, Oracle, SQL Server, SQLite, MongoDB, Redis, Couchbase, ClickHouse and Apache Druid — behind one unified interface, plus LibreDB, our own embedded engine.',
slug: 'providers',
pageTitle: 'Supported Providers — PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis & LibreDB',
pageDescription:
Expand Down
2 changes: 2 additions & 0 deletions src/pages/[section].astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import SectionShell from '../components/studio/SectionShell.astro';
import { sections, sectionById } from '../data/sections';
import { sectionSeo } from '../data/section-seo';

import ManifestoSection from '../components/sections/ManifestoSection.astro';
import FeaturesSection from '../components/sections/FeaturesSection.astro';
import ProvidersSection from '../components/sections/ProvidersSection.astro';
import CompareSection from '../components/sections/CompareSection.astro';
Expand All @@ -29,6 +30,7 @@ export function getStaticPaths() {
}

const COMPONENTS: Record<string, any> = {
manifesto: ManifestoSection,
features: FeaturesSection,
providers: ProvidersSection,
compare: CompareSection,
Expand Down
Loading