diff --git a/CHANGES.rst b/CHANGES.rst
index c68dbedb..59c1b2d9 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -6,6 +6,12 @@ CHANGES
Unreleased
----------
+2026/02/22 0.50.1
+-----------------
+- Fix: CSS now loads independently of JavaScript, reducing load time and
+preventing unstyled pages on slow connections.
+- Navigation: Preload pages on hover so first-visit TOC clicks feel instant.
+
2026/02/20 0.50.0
-----------------
- Navigation: Added references to CrateDB MCP and CrateDB Toolkit
diff --git a/package.json b/package.json
index a39b7c0b..fc8699ae 100644
--- a/package.json
+++ b/package.json
@@ -5,6 +5,7 @@
"expose-loader": "^5.0",
"jquery": "^4.0.0",
"js-cookie": "^3.0.5",
+ "mini-css-extract-plugin": "^2.10.0",
"normalize.css": "^8.0.1",
"postcss-loader": "^8.2",
"sass": "^1.97.3",
@@ -21,6 +22,7 @@
"minimist": "^1.2.7"
},
"dependencies": {
+ "@swup/preload-plugin": "^3.2.11",
"swup": "^4.8.2",
"swup-morph-plugin": "^1.3.0"
}
diff --git a/src/crate/theme/rtd/__init__.py b/src/crate/theme/rtd/__init__.py
index 685e6c12..74a07490 100644
--- a/src/crate/theme/rtd/__init__.py
+++ b/src/crate/theme/rtd/__init__.py
@@ -23,7 +23,7 @@
import os
-VERSION = (0, 50, 0)
+VERSION = (0, 50, 1)
__version__ = ".".join(str(v) for v in VERSION) # + ".dev0"
__version_full__ = __version__
diff --git a/src/crate/theme/rtd/crate/base.html b/src/crate/theme/rtd/crate/base.html
index 56777719..78670d5c 100644
--- a/src/crate/theme/rtd/crate/base.html
+++ b/src/crate/theme/rtd/crate/base.html
@@ -106,6 +106,7 @@
{%- endblock styles -%}
+
{#- Custom front matter #}
{%- block extrahead -%}{%- endblock -%}
diff --git a/src/crate/theme/rtd/crate/static/js/swup.js b/src/crate/theme/rtd/crate/static/js/swup.js
index 853b62df..3cdf727c 100644
--- a/src/crate/theme/rtd/crate/static/js/swup.js
+++ b/src/crate/theme/rtd/crate/static/js/swup.js
@@ -17,6 +17,7 @@
import Swup from 'swup';
import SwupMorphPlugin from 'swup-morph-plugin';
+import SwupPreloadPlugin from '@swup/preload-plugin';
const SIDEBAR_SELECTOR = '.sidebar-tree';
const MAIN_CONTAINER_SELECTOR = 'main.sb-main';
@@ -340,7 +341,7 @@ export function initSwup() {
// Morph main content in-place rather than replacing it wholesale,
// which avoids layout thrash and preserves focus/scroll in the content area.
- plugins: [new SwupMorphPlugin()],
+ plugins: [new SwupMorphPlugin(), new SwupPreloadPlugin()],
// Disable animation detection warnings when no transition-* classes exist
animationSelector: false,
diff --git a/webpack.config.js b/webpack.config.js
index 2d185a36..a24eb6f2 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,7 +1,11 @@
const path = require('path');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/index.js',
+ plugins: [
+ new MiniCssExtractPlugin({ filename: 'main.css' }),
+ ],
module: {
rules: [
{
@@ -10,7 +14,7 @@ module.exports = {
/\.s[ac]ss$/i,
],
use: [
- { loader: "style-loader" },
+ MiniCssExtractPlugin.loader,
{ loader: "css-loader", options: { sourceMap: true } },
{ loader: "postcss-loader", options: { sourceMap: true } },
{ loader: "sass-loader", options: { api: "legacy", sourceMap: true } },
diff --git a/yarn.lock b/yarn.lock
index 337da678..175cfa3c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -178,6 +178,13 @@
dependencies:
swup "^4.0.0"
+"@swup/preload-plugin@^3.2.11":
+ version "3.2.11"
+ resolved "https://registry.yarnpkg.com/@swup/preload-plugin/-/preload-plugin-3.2.11.tgz#990f22103a527e8f6c3da0ef96c5a2c6075b43a1"
+ integrity sha512-dq50u+d8L+63/pU6dUDnypuBoF49ubjRzRJqitGem2K7wRn7xccxRSvdyeGKdA2vNvzGDAmLfwVTZdSotvvDrw==
+ dependencies:
+ "@swup/plugin" "^4.0.0"
+
"@types/eslint-scope@^3.7.7":
version "3.7.7"
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5"
@@ -999,6 +1006,14 @@ mime-types@^2.1.27:
dependencies:
mime-db "1.47.0"
+mini-css-extract-plugin@^2.10.0:
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.0.tgz#d801a1f388f8fac7333c01b7c15c9222c811def4"
+ integrity sha512-540P2c5dYnJlyJxTaSloliZexv8rji6rY8FhQN+WF/82iHQfA23j/xtJx97L+mXOML27EqksSek/g4eK7jaL3g==
+ dependencies:
+ schema-utils "^4.0.0"
+ tapable "^2.2.1"
+
minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
@@ -1285,7 +1300,7 @@ sass@^1.97.3:
optionalDependencies:
"@parcel/watcher" "^2.4.1"
-schema-utils@^4.3.0, schema-utils@^4.3.3:
+schema-utils@^4.0.0, schema-utils@^4.3.0, schema-utils@^4.3.3:
version "4.3.3"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.3.tgz#5b1850912fa31df90716963d45d9121fdfc09f46"
integrity sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==
@@ -1411,7 +1426,7 @@ swup@^4.0.0, swup@^4.8.2:
opencollective-postinstall "^2.0.2"
path-to-regexp "^6.2.1"
-tapable@^2.2.0, tapable@^2.3.0:
+tapable@^2.2.0, tapable@^2.2.1, tapable@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.0.tgz#7e3ea6d5ca31ba8e078b560f0d83ce9a14aa8be6"
integrity sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==