Skip to content
31 changes: 31 additions & 0 deletions docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,37 @@ module.exports = {
href: "https://keploy.io/",
},
},
// Algolia search
{
tagName: "link",
attributes: {
rel: "preconnect",
href: "https://WZTL8PLCOD-dsn.algolia.net",
crossorigin: "anonymous",
},
},
// Analytics (dns-prefetch only — not render-blocking)
{
tagName: "link",
attributes: {
rel: "dns-prefetch",
href: "https://www.clarity.ms",
},
},
{
tagName: "link",
attributes: {
rel: "dns-prefetch",
href: "https://www.googletagmanager.com",
},
},
{
tagName: "link",
attributes: {
rel: "dns-prefetch",
href: "https://www.google-analytics.com",
},
},
// Site-wide entity graph (Organization, WebSite, SoftwareApplication).
// These used to be three sibling <script> blocks, each re-declaring its
// own publisher, which left several disconnected Organization nodes on
Expand Down
33 changes: 32 additions & 1 deletion netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,38 @@
## Note: if you are looking for Redirects
# they have been moved to /static/_redirects to make it more manageable - swyx

# Security headers for all pages
# ── Performance: Cache headers ────────────────────────────────────────────────
# Hashed JS/CSS bundles emitted by Docusaurus/webpack → safe to cache 1 year
[[headers]]
for = "/docs/assets/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"

# Static images served from /img
[[headers]]
for = "/img/*"
[headers.values]
Cache-Control = "public, max-age=86400, stale-while-revalidate=604800"

# Fonts are NOT content-hashed (e.g. Roboto-Bold.woff2) so immutable is unsafe.
# Use a 1-week cache with stale-while-revalidate instead.
[[headers]]
for = "/fonts/*"
[headers.values]
Cache-Control = "public, max-age=604800, stale-while-revalidate=86400"

# Static JS helpers (non-hashed scripts in /docs/js and /docs/scripts)
[[headers]]
for = "/js/*"
[headers.values]
Cache-Control = "public, max-age=86400"

[[headers]]
for = "/scripts/*"
[headers.values]
Cache-Control = "public, max-age=86400"

# ── Security headers (improves PageSpeed Best Practices score) ──────────────
[[headers]]
for = "/*"
[headers.values]
Expand Down
43 changes: 31 additions & 12 deletions src/components/responsive-player/ResponsivePlayer.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,41 @@
import React from "react";
import ReactPlayer from "react-player";
import React, {Suspense, lazy} from "react";

// Lazy-load react-player so it is NOT included in the initial JS bundle.
// react-player/lazy defers loading the actual player implementation until
// the component is rendered, reducing the first-page-load JS payload.
const ReactPlayer = lazy(() => import("react-player/lazy"));

function ResponsivePlayer({url, loop, playing}) {
return (
<div
className="relative rounded-lg shadow-lg"
style={{paddingTop: "56.25%"}}
>
{/* /* Player ratio: 100 / (1280 / 720) */}
<ReactPlayer
className="absolute left-0 top-0"
url={url}
loop={loop}
playing={playing}
width="100%"
height="100%"
controls={true}
/>
{/* Player ratio: 100 / (1280 / 720) */}
<Suspense
fallback={
<div
className="absolute left-0 top-0 flex h-full w-full items-center justify-center bg-gray-100 dark:bg-gray-800"
role="status"
aria-label="Loading video player"
>
<div className="h-8 w-8 animate-spin rounded-full border-2 border-gray-400 border-t-transparent dark:border-gray-500" />
<span className="ml-3 text-sm font-medium text-gray-600 dark:text-gray-300">
Loading video player...
</span>
</div>
}
>
<ReactPlayer
className="absolute left-0 top-0"
url={url}
loop={loop}
playing={playing}
width="100%"
height="100%"
controls={true}
/>
</Suspense>
</div>
);
}
Expand Down
50 changes: 49 additions & 1 deletion src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,8 @@ td img {
margin: 0;
}

.codeBlockContainer_node_modules-\@docusaurus-theme-classic-lib-next-theme-CodeBlock-styles-module {
[class^="codeBlockContainer_"],
[class*=" codeBlockContainer_"] {
box-shadow: none !important;
margin: 0;
padding: 0;
Expand Down Expand Up @@ -3175,3 +3176,50 @@ html[data-theme="dark"] .docs-inline-footer__slack {
font-size: 0.95rem;
}
}

/* ===== PERFORMANCE: Rendering & paint optimisations ===== */

/*
* content-visibility: auto — lets the browser skip layout/paint for
* off-screen sections, reducing LCP and INP on mobile.
* contain-intrinsic-size gives the browser a size estimate so the
* scroll-bar doesn't jump when content is rendered.
*/
footer,
.footer {
content-visibility: auto;
contain-intrinsic-size: 0 200px;
}

/* Sidebar is always below the fold on small viewports */
@media (max-width: 996px) {
.theme-doc-sidebar-container {
content-visibility: auto;
contain-intrinsic-size: 0 600px;
}
}

/*
* Lazy-decoded images — any <img> without an explicit loading attribute
* should at minimum decode off the main thread.
*/
img:not([loading]) {
decoding: async;
}

/*
* Reduce paint layers for the announcement bar (it's a position:sticky
* element and can cause extra compositing cost on mobile).
* Using attribute substring selector to avoid relying on a hashed class name
* that changes between Docusaurus builds.
*/
[class*="announcementBar"] {
will-change: auto;
transform: translateZ(0);
}

/*
* Font-display: swap is configured per @font-face declaration in
* src/fonts. Docusaurus-injected Google Fonts links already include
* &display=swap in the URL, so no additional override is needed here.
*/
Loading