PageSpeed flagged 470ms of render-blocking requests: all three template stylesheets plus a Google Fonts request carrying all six families loaded on every page view, though only one template is active per load (warp switches reload the page). The head script that resolves the template before paint now injects just that template's stylesheet (with blocking=render to avoid a theme flash) and a per-template font subset loaded off the critical path via the media=print onload swap. Only the base styles.css remains render-blocking. Claude-Session: https://claude.ai/code/session_011XPqEdbBpGpuD6PucEuU7E
89 lines
4.2 KiB
HTML
89 lines
4.2 KiB
HTML
<!doctype html>
|
|
<html lang="en" data-theme="auto" data-template="editorial">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
|
<meta name="color-scheme" content="light dark">
|
|
<meta name="description" content="Joel Brock — consulting technologist in Portland, OR. Links to my work in cooperative technology, projects, and video.">
|
|
|
|
<title>Links — index</title>
|
|
|
|
<link rel="icon" type="image/svg+xml" href="favicon.svg">
|
|
<link rel="alternate icon" type="image/png" href="data:image/png;base64,">
|
|
|
|
<!-- Preconnect to font + favicon services for snappy first paint -->
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link rel="preconnect" href="https://www.google.com">
|
|
<link rel="preconnect" href="https://i.ytimg.com">
|
|
|
|
<script>
|
|
// Apply saved theme + template before paint to avoid flash.
|
|
// URL ?template=… wins over the cached value so deep links work.
|
|
try {
|
|
var t = localStorage.getItem("dlstack-theme");
|
|
if (t === "light" || t === "dark") document.documentElement.dataset.theme = t;
|
|
var qtpl = null;
|
|
try { qtpl = new URL(location.href).searchParams.get("template"); } catch (e) {}
|
|
if (qtpl === "swiss" || qtpl === "editorial" || qtpl === "cosmos") {
|
|
document.documentElement.dataset.template = qtpl;
|
|
} else {
|
|
var tpl = localStorage.getItem("dlstack-template");
|
|
if (tpl === "swiss" || tpl === "editorial" || tpl === "cosmos") document.documentElement.dataset.template = tpl;
|
|
}
|
|
} catch (e) {}
|
|
|
|
// Load only the active template's stylesheet and font families.
|
|
// Template switches reload the page (app.js "warp"), so the inactive
|
|
// templates' CSS and fonts are never needed on this page load.
|
|
(function () {
|
|
var tpl = document.documentElement.dataset.template || "editorial";
|
|
if (tpl === "swiss" || tpl === "cosmos") {
|
|
var css = document.createElement("link");
|
|
css.rel = "stylesheet";
|
|
css.href = "assets/css/" + tpl + ".css";
|
|
// Script-inserted sheets don't block paint by default; opt in so the
|
|
// theme never flashes unstyled where blocking=render is supported.
|
|
css.setAttribute("blocking", "render");
|
|
document.head.appendChild(css);
|
|
}
|
|
// Editorial: Fraunces (variable serif) + DM Serif Display + Geist + Geist Mono
|
|
// Swiss: Archivo (variable grotesque, near-Akzidenz/Univers)
|
|
// Cosmos: Orbitron + Geist + Geist Mono
|
|
var families = {
|
|
editorial: "family=DM+Serif+Display:ital@0;1&family=Fraunces:opsz,wght,SOFT,WONK@9..144,300..600,30..100,0..1&family=Geist:wght@300;400;500;600&family=Geist+Mono:wght@400;500",
|
|
swiss: "family=Archivo:wght@400;500;600;700;900",
|
|
cosmos: "family=Geist:wght@300;400;500;600&family=Geist+Mono:wght@400;500&family=Orbitron:wght@400;500;700;900"
|
|
};
|
|
var fonts = document.createElement("link");
|
|
fonts.rel = "stylesheet";
|
|
fonts.href = "https://fonts.googleapis.com/css2?" + (families[tpl] || families.editorial) + "&display=swap";
|
|
// media=print keeps the request off the critical path; flip to all once
|
|
// loaded. display=swap means text renders in fallbacks meanwhile.
|
|
fonts.media = "print";
|
|
fonts.onload = function () { this.media = "all"; };
|
|
document.head.appendChild(fonts);
|
|
})();
|
|
</script>
|
|
|
|
<link rel="stylesheet" href="assets/css/styles.css">
|
|
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:title" content="Joel Brock — links">
|
|
<meta property="og:description" content="Consulting technologist in Portland, OR. Cooperative technology, projects, and video.">
|
|
<meta name="twitter:card" content="summary">
|
|
</head>
|
|
<body>
|
|
<a class="sr-only" href="#app">Skip to content</a>
|
|
<div class="shell" id="app">
|
|
<noscript>
|
|
<p style="color:var(--accent);font-family:var(--mono);padding:2rem;max-width:48ch">
|
|
JavaScript is required to render this page — it reads the link list from <code>data/links.json</code>.
|
|
Enable JavaScript and reload, or browse <a href="data/links.json">the raw data file</a>.
|
|
</p>
|
|
</noscript>
|
|
</div>
|
|
<script src="assets/js/app.js" defer></script>
|
|
</body>
|
|
</html>
|