diff --git a/website/src/components/tutorial/tutorialTheme.js b/website/src/components/tutorial/tutorialTheme.js
index 79352f804..0b8d19518 100644
--- a/website/src/components/tutorial/tutorialTheme.js
+++ b/website/src/components/tutorial/tutorialTheme.js
@@ -130,6 +130,15 @@ export function editor({file, tag, code, sql, copy, variants}) {
`;
}
+// A one-line "$ " shell bar with a Copy button, matching the editor
+// copy control. `command` is copied verbatim (without the leading $). Wired by
+// wireSqlToggles(), so pages that render a clonebar() must call it in useEffect.
+export function clonebar(command) {
+ const data = esc(command).replace(/"/g, '"');
+ return `
$${esc(command)}` +
+ `
`;
+}
+
// A compact two-pane "at a glance" comparison for one-liner contrasts. Only
// use where both snippets are genuinely short; full examples stay sequential.
export function glance({left, right}) {
@@ -140,8 +149,43 @@ export function glance({left, right}) {
`;
}
-// Wires up every "Show SQL" and "Copy" button rendered by editor(). Returns a
-// cleanup function for the calling useEffect.
+// Wires one .copybtn: copies its data-copy to the clipboard and flips the label
+// to "Copied" for a moment. Returns a cleanup function.
+function attachCopy(copyBtn) {
+ const txt = copyBtn.querySelector('.copybtntext');
+ let timer = null;
+ const onCopy = () => {
+ const text = copyBtn.dataset.copy;
+ // The Clipboard API needs a secure context; fall back to a throwaway
+ // textarea so copy also works on plain-http previews (e.g. LAN).
+ if (navigator.clipboard && window.isSecureContext) {
+ navigator.clipboard.writeText(text);
+ } else {
+ const ta = document.createElement('textarea');
+ ta.value = text;
+ document.body.appendChild(ta);
+ ta.select();
+ document.execCommand('copy');
+ ta.remove();
+ }
+ copyBtn.classList.add('on');
+ if (txt) txt.textContent = 'Copied';
+ clearTimeout(timer);
+ timer = setTimeout(() => {
+ copyBtn.classList.remove('on');
+ if (txt) txt.textContent = 'Copy';
+ }, 1600);
+ };
+ copyBtn.addEventListener('click', onCopy);
+ return () => {
+ copyBtn.removeEventListener('click', onCopy);
+ clearTimeout(timer);
+ };
+}
+
+// Wires up every "Show SQL" and "Copy" button rendered by editor(), plus the
+// Copy button on any clonebar(). Returns a cleanup function for the calling
+// useEffect.
export function wireSqlToggles() {
const cleanups = [];
document.querySelectorAll('.storm-tut .editor').forEach((ed) => {
@@ -157,37 +201,7 @@ export function wireSqlToggles() {
cleanups.push(() => btn.removeEventListener('click', onClick));
}
const copyBtn = ed.querySelector('.copybtn');
- if (copyBtn) {
- const txt = copyBtn.querySelector('.copybtntext');
- let timer = null;
- const onCopy = () => {
- const text = copyBtn.dataset.copy;
- // The Clipboard API needs a secure context; fall back to a throwaway
- // textarea so copy also works on plain-http previews (e.g. LAN).
- if (navigator.clipboard && window.isSecureContext) {
- navigator.clipboard.writeText(text);
- } else {
- const ta = document.createElement('textarea');
- ta.value = text;
- document.body.appendChild(ta);
- ta.select();
- document.execCommand('copy');
- ta.remove();
- }
- copyBtn.classList.add('on');
- if (txt) txt.textContent = 'Copied';
- clearTimeout(timer);
- timer = setTimeout(() => {
- copyBtn.classList.remove('on');
- if (txt) txt.textContent = 'Copy';
- }, 1600);
- };
- copyBtn.addEventListener('click', onCopy);
- cleanups.push(() => {
- copyBtn.removeEventListener('click', onCopy);
- clearTimeout(timer);
- });
- }
+ if (copyBtn) cleanups.push(attachCopy(copyBtn));
const sel = ed.querySelector('.varsel');
if (sel) {
const panes = ed.querySelectorAll('.varpane');
@@ -202,6 +216,9 @@ export function wireSqlToggles() {
cleanups.push(() => sel.removeEventListener('change', onChange));
}
});
+ document.querySelectorAll('.storm-tut .clonebar .copybtn').forEach((copyBtn) => {
+ cleanups.push(attachCopy(copyBtn));
+ });
return () => cleanups.forEach((fn) => fn());
}
@@ -215,7 +232,7 @@ export function TutorialPage({title, description, slug, body}) {
<>
- {`${title} · Storm Tutorials`}
+ {`${title} · ST/ORM Tutorials`}
@@ -342,6 +359,8 @@ export const TUT_CSS = `
.storm-tut .sqlbtn:hover,.storm-tut .copybtn:hover{background:rgba(129,140,248,.12);border-color:rgba(129,140,248,.5)}
.storm-tut .sqlbtn.on,.storm-tut .copybtn.on{background:rgba(129,140,248,.16);color:#aab2ff}
.storm-tut .sqlbtn .ico,.storm-tut .copybtn .ico{width:13px;height:13px;opacity:.9}
+ .storm-tut .clonebar .clonecmd{overflow-x:auto}
+ .storm-tut .clonebar .copybtn{margin-left:auto;flex:none;gap:0;padding:5px 8px}
/* variant selector (same chrome as the buttons; native select behind a
custom chevron because appearance:none drops the platform arrow) */
.storm-tut .varwrap{position:relative;margin-left:14px;display:inline-flex;align-items:center}
diff --git a/website/src/css/custom.css b/website/src/css/custom.css
index cd8f603fe..8d35dd550 100644
--- a/website/src/css/custom.css
+++ b/website/src/css/custom.css
@@ -1,22 +1,79 @@
+/* Docs (Infima) theme aligned with the marketing site's dark palette. The
+ custom landing/tutorial/blog pages carry their own dark shell; these variables
+ bring the Docusaurus-chrome pages (/docs) onto the same tokens: background
+ #070709, panels #0f0f14, text #eaeaf0, indigo accent #818cf8, borders #20202a,
+ and the Inter / JetBrains Mono type pair. Default mode is dark (see
+ docusaurus.config.ts colorMode); the light theme keeps a readable purple. */
+
:root {
- --ifm-color-primary: #3949ab;
- --ifm-color-primary-dark: #303f9f;
- --ifm-color-primary-darker: #283593;
- --ifm-color-primary-darkest: #1a237e;
- --ifm-color-primary-light: #5c6bc0;
- --ifm-color-primary-lighter: #7986cb;
- --ifm-color-primary-lightest: #9fa8da;
- --ifm-code-font-size: 95%;
+ /* Type pair shared with the marketing pages. */
+ --ifm-font-family-base: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
+ --ifm-font-family-monospace: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
+ --ifm-code-font-size: 92%;
+
+ /* Light theme uses a darker indigo so buttons/links keep contrast on white. */
+ --ifm-color-primary: #4f46e5;
+ --ifm-color-primary-dark: #4740ce;
+ --ifm-color-primary-darker: #433cc2;
+ --ifm-color-primary-darkest: #3731a0;
+ --ifm-color-primary-light: #6a62e9;
+ --ifm-color-primary-lighter: #7972eb;
+ --ifm-color-primary-lightest: #9d98f0;
}
[data-theme='dark'] {
- --ifm-color-primary: #7986cb;
- --ifm-color-primary-dark: #5c6bc0;
- --ifm-color-primary-darker: #3949ab;
- --ifm-color-primary-darkest: #303f9f;
- --ifm-color-primary-light: #9fa8da;
- --ifm-color-primary-lighter: #c5cae9;
- --ifm-color-primary-lightest: #e8eaf6;
+ /* Accent: the marketing --accent (#818cf8), the lighter shade on dark. */
+ --ifm-color-primary: #818cf8;
+ --ifm-color-primary-dark: #6470f6;
+ --ifm-color-primary-darker: #5563f5;
+ --ifm-color-primary-darkest: #2b3cf2;
+ --ifm-color-primary-light: #9ea8fa;
+ --ifm-color-primary-lighter: #adb5fb;
+ --ifm-color-primary-lightest: #d8dcfe;
+
+ /* Surfaces and text mapped from the site tokens. */
+ --ifm-background-color: #070709;
+ --ifm-background-surface-color: #0f0f14;
+ --ifm-navbar-background-color: #0b0b0f;
+ --ifm-footer-background-color: #0b0b0f;
+ --ifm-font-color-base: #eaeaf0;
+ --ifm-heading-color: #eaeaf0;
+ --ifm-color-content: #b7b8c2;
+ --ifm-color-content-secondary: #8a8a96;
+
+ /* Borders / rules → --border #20202a, softened via the emphasis ramp. */
+ --ifm-toc-border-color: #20202a;
+ --ifm-table-border-color: #20202a;
+ --ifm-hr-border-color: #20202a;
+ --ifm-color-emphasis-100: #0f0f14;
+ --ifm-color-emphasis-200: #17171f;
+ --ifm-color-emphasis-300: #20202a;
+
+ /* Links, sidebar menu, breadcrumbs → accent. */
+ --ifm-link-color: #a5b4fc;
+ --ifm-menu-color: #b7b8c2;
+ --ifm-menu-color-active: #a5b4fc;
+ --ifm-menu-color-background-active: rgba(129, 140, 248, 0.08);
+ --ifm-menu-color-background-hover: rgba(129, 140, 248, 0.06);
+ --ifm-breadcrumb-color-active: #a5b4fc;
+ --ifm-breadcrumb-item-background-active: rgba(129, 140, 248, 0.1);
+
+ /* Code blocks → panel background (dracula tokens still read fine on it). */
+ --ifm-code-background: #0f0f14;
+ --prism-background-color: #0b0b0f;
+ --docusaurus-highlighted-code-line-bg: rgba(129, 140, 248, 0.14);
+}
+
+/* Navbar: subtle bottom rule like the marketing nav. */
+[data-theme='dark'] .navbar {
+ border-bottom: 1px solid #17171f;
+ box-shadow: none;
+}
+
+/* Inline code chips: match the marketing --panel/--border-soft look. */
+[data-theme='dark'] code {
+ background: #0f0f14;
+ border: 1px solid #17171f;
}
/* Cleaner tables in docs and blog. Infima draws a full cell grid (vertical +
diff --git a/website/src/pages/benchmarks.js b/website/src/pages/benchmarks.js
index d4eaa5c74..f569c0855 100644
--- a/website/src/pages/benchmarks.js
+++ b/website/src/pages/benchmarks.js
@@ -1,11 +1,11 @@
import React, {useEffect} from 'react';
import Head from '@docusaurus/Head';
import {
- TUT_CSS, navHtml, FOOT_HTML, wireSqlToggles, editor,
+ TUT_CSS, navHtml, FOOT_HTML, wireSqlToggles, editor, clonebar,
K, T, S, C, F, N, A, P, QK, QQ,
} from '../components/tutorial/tutorialTheme';
-const TITLE = 'Benchmarks · Storm ORM vs Hibernate, jOOQ, Exposed and Jimmer';
+const TITLE = 'Benchmarks · ST/ORM vs Hibernate, jOOQ, Exposed and Jimmer';
const DESC = 'Reproducible JMH benchmarks of Storm against JDBC, Hibernate, jOOQ, Exposed and Jimmer on PostgreSQL 17, with the entity and query code behind every number.';
// Results from the reproducible suite: one tuned PostgreSQL 17 container over TCP, JMH, 2 forks,
@@ -486,7 +486,7 @@ ${charts}
The repository contains the full methodology, the statement-log auditing tools used to verify round-trip counts, and every implementation in full; scripts/run.sh reproduces the numbers.
+ ${clonebar('git clone https://github.com/storm-orm/storm-benchmarks.git')}
View on GitHub →
diff --git a/website/src/pages/blog/index.js b/website/src/pages/blog/index.js
index e7efdb2bd..5003138c4 100644
--- a/website/src/pages/blog/index.js
+++ b/website/src/pages/blog/index.js
@@ -7,7 +7,7 @@ import {TUT_CSS, navHtml, FOOT_HTML} from '../../components/tutorial/tutorialThe
// matches the tutorials and examples. Each article lives next to this file as
// its own custom page; keep this list newest-first and in sync with them.
-const TITLE = 'Storm Blog · Design decisions and deep dives';
+const TITLE = 'ST/ORM Blog · Design decisions and deep dives';
const DESC =
'The design decisions behind ST/ORM, deep dives into how it works, and the ' +
'thinking that shapes the API. Plain values, explicit SQL, and no hidden ' +
diff --git a/website/src/pages/comparison.js b/website/src/pages/comparison.js
index fae1c1fd9..58ce65b2f 100644
--- a/website/src/pages/comparison.js
+++ b/website/src/pages/comparison.js
@@ -12,7 +12,7 @@ import {TUT_CSS, navHtml, FOOT_HTML, wireSqlToggles} from '../components/tutoria
// only differences that are real and that the rival does not already cover
// are called out.
-const TITLE = 'Comparison · Storm vs JPA, jOOQ, Exposed, Jimmer';
+const TITLE = 'Comparison · ST/ORM vs JPA, jOOQ, Exposed, Jimmer';
const DESC =
'How Storm compares to Hibernate/JPA, Spring Data, jOOQ, Exposed, Ktorm, ' +
'MyBatis, and Jimmer. A decision matrix plus a short, fair take on each, with ' +
diff --git a/website/src/pages/examples/index.js b/website/src/pages/examples/index.js
index d2389f75d..3a86cf416 100644
--- a/website/src/pages/examples/index.js
+++ b/website/src/pages/examples/index.js
@@ -8,7 +8,7 @@ import {TUT_CSS, navHtml, FOOT_HTML} from '../../components/tutorial/tutorialThe
// and Java. Each card links to its detail page (README rendered inline by
// the example-readmes plugin, with the clone command and GitHub link).
-const TITLE = 'Storm Example Projects · Complete applications built with Storm';
+const TITLE = 'ST/ORM Example Projects · Complete applications built with Storm';
const DESC =
'Complete example applications built with Storm ORM: a movie browser on ' +
'the public IMDB dataset, implemented on Spring Boot 4 and Ktor, in Kotlin ' +
diff --git a/website/src/pages/index.js b/website/src/pages/index.js
index f93f26450..718f67c33 100644
--- a/website/src/pages/index.js
+++ b/website/src/pages/index.js
@@ -774,7 +774,7 @@ export default function Home() {
<>
- Storm · The type-safe Kotlin ORM
+ ST/ORM · The type-safe Kotlin ORM