<!DOCTYPE html>
<html lang="en" class="theme-device">
<head>
<title>fasterthanli.me</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="impact-site-verification" value="805abea2-eaaa-4a33-8250-9448e4976bd2">
<meta name="amos-face" content="https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/amos-face~6eabffd6c6ca3b04.avif">
<link rel="icon" type="image/jxl" href="https://cdn.fasterthanli.me/content/img/favicon~72ac4ba96bed6dad.jxl">
<link rel="icon" type="image/webp" href="https://cdn.fasterthanli.me/content/img/favicon~679ae9c272874bba.webp">
<link rel="icon" type="image/avif" href="https://cdn.fasterthanli.me/content/img/favicon~fc5931f361bf516c.avif">
<meta property="og:site_name" content="fasterthanli.me">
<meta property="og:locale" content="en-us">
<meta property="og:type" content="article">
<meta property="og:url" content="">
<meta name="theme-color" content="#f64c4c">
<meta property="og:title" content="fasterthanli.me"><meta property="og:image" content="https://cdn.fasterthanli.me/content/_thumb~6122e1366bbad676.png">
<meta property="og:image:width" content="1920">
<meta property="og:image:height" content="1080">
<meta property="og:description" content="Hi! I’m Amos, better known as @fasterthanlime.
I make articles and videos about how computers work. My content is long-form, didactic and exploratory — and often an excuse to teach Rust!
I also co-...">
<meta name="description" content="Hi! I’m Amos, better known as @fasterthanlime.
I make articles and videos about how computers work. My content is long-form, didactic and exploratory — and often an excuse to teach Rust!
I also co-...">
<meta name="author" content="Amos Wenger"><meta property="article:published_time" content="2024-08-27T07:30:00Z"><link href="/index.xml" type="application/atom+xml" rel="alternate" title="Sitewide Atom feed">
<style>
@font-face {
font-family: "ZedTextFtl";
src: url(https://cdn.fasterthanli.me/content/fonts/ZedTextL-Regular~69f269ea849a04f6.woff2) format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "ZedTextFtl";
src: url(https://cdn.fasterthanli.me/content/fonts/ZedTextL-Bold~f8c62afa20558c5b.woff2) format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "SymbolsNfMonoFtl";
src: url(https://cdn.fasterthanli.me/content/fonts/SymbolsNerdFontMono-Regular-subset~592f1c6ab55eb2ef.woff2) format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "IosevkaFtl";
src: url(https://cdn.fasterthanli.me/content/fonts/IosevkaFTLNerdFont-Regular-subset~bf272da82490b046.woff2) format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "IosevkaFtl";
src: url(https://cdn.fasterthanli.me/content/fonts/IosevkaFTLNerdFont-Bold-subset~1b29fcdaf00aca13.woff2) format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "ZedDisplayFtl";
src: url(https://cdn.fasterthanli.me/content/fonts/ZedDisplayL-Heavy~d4e1b849e7cfad26.woff2) format("woff2");
font-weight: 800;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "BerkeleyMonoFtl";
src: url(https://cdn.fasterthanli.me/content/fonts/BerkeleyMono-Condensed~53d681071fb8e699.woff2) format("woff2");
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "BerkeleyMonoFtl";
src: url(https://cdn.fasterthanli.me/content/fonts/BerkeleyMono-Bold-Condensed~53932dfc510a8962.woff2) format("woff2");
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "BerkeleyMonoFtl";
src: url(https://cdn.fasterthanli.me/content/fonts/BerkeleyMono-Condensed-Oblique~47fd27e8529fd046.woff2) format("woff2");
font-weight: 400;
font-style: oblique;
font-display: swap;
}
@font-face {
font-family: "BerkeleyMonoFtl";
src: url(https://cdn.fasterthanli.me/content/fonts/BerkeleyMono-Bold-Condensed-Oblique~46de397d0dd66acd.woff2) format("woff2");
font-weight: 700;
font-style: oblique;
font-display: swap;
}
@font-face {
font-family: "BerkeleyMonoFtl";
src: url(https://cdn.fasterthanli.me/content/fonts/BerkeleyMono-Condensed-Oblique~47fd27e8529fd046.woff2) format("woff2");
font-weight: 400;
font-style: oblique;
font-display: swap;
}
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
box-sizing: border-box;
}
:root {
--small-bp-under: 699px;
--medium-bp-over: 700px;
--medium-large-bp-over: 950px;
--large-bp-over: 1400px;
--font-size-base: 13.24px;
--border-radius: 0.4rem;
--secondary-color: light-dark(#24213f, #333);
--topnav-height: 3.5em;
--font-inline-code-size: 1em;
--font-display: "ZedDisplayFtl", sans-serif;
--font-title: "ZedDisplayFtl", sans-serif;
--font-text: "ZedTextFtl", sans-serif;
--font-ui: "ZedTextFtl", sans-serif;
--font-code: "IosevkaFtl", "SymbolsNfMonoFtl", monospace;
--font-symbol: "SymbolsNfMonoFtl", monospace;
--ftl-blue: #588dde;
--ftl-blue-light: #5c8fee;
--line-height: 1.74;
--page-width: 920px;
--present-page-width: 45vw;
--dark-bg: #1f1f1f;
--dark-bg-2: #282828;
--inlay-bg: #f6f6f6;
--inlay-bg-dark: #282828;
--p-black: #1b1f23;
--p-white-dark: black;
--p-white: #fff;
--p-black-dark: white;
--amos-color: light-dark(#c3e1fd4d, #4b56694d);
--amos-border-color: light-dark(#9bc3e8cc, #67a3c366);
--bear-color: light-dark(#f7eebd4d, #4d4d4d4d);
--bear-border-color: light-dark(#e9d992cc, #c3b16766);
--exclusive-border-color: light-dark(#b49d4e, color-mix(in srgb, #a1872e, black 10%));
--exclusive-background-color: light-dark(color-mix(in srgb, #fffbdf, white 4%), color-mix(in srgb, color-mix(in srgb, #261c01, transparent 12%), white 10%));
--exclusive-chip-bg-color: light-dark(#f7e53a, #f7de35);
--exclusive-chip-text-color: rgb(50, 50, 50);
--secondary-text-color: light-dark(#636363, #d8d8d8);
--accent-color: light-dark(#496fcc, #5f80df);
--link-color: var(--accent-color);
--text-decoration-thickness: 1px;
--text-decoration-color: color-mix(in srgb, var(--link-color) 77%, transparent);
--visited-link-color: light-dark(#8223c1, color(#8223c1 lightness(+30%)));
--discreet-link-color: var(--link-color);
--secondary-color: light-dark(#24213f, #333);
--secondary-border-color: light-dark(
color-mix(in srgb, #24213f 97%, black 3%),
color-mix(in srgb, #333 85%, black 15%)
);
--code-border-color: transparent;
--code-font-size: 1.1rem;
--text-font-size: 1.1rem;
--ui-font-size: 0.95rem;
--box-shadow-color: light-dark(#ccc, #3a3a3a);
--page-html-bg: light-dark(#fefeff, #0f0f0f);
--secondary-bg: light-dark(#fafafa, #1a1a1a);
--html-bg: light-dark(#f9f9fa, #0a0a0a);
--p-white: #fff;
--p-black: #1b1f23;
--border-color: light-dark(#e2e8f0, #232323);
--page-padding-inline: 1.4rem;
--page-padding-block: 1.4rem;
}
@media (max-width: 699px) {
:root {
--page-padding-inline: 1.2rem;
--page-padding-block: 0.9rem;
}
}
@media (min-width: 700px) {
:root {
--page-padding-inline: 3.1rem;
--page-padding-block: 1.4rem;
}
}
@media (min-width: 1400px) {
:root {
--page-padding-inline: 4.2rem;
--page-padding-block: 1.8rem;
}
}
html {
font-family: var(--font-text);
background: var(--html-bg);
color: light-dark(#1a1a1e, #e0e0e0);
font-size: var(--font-size-base);
scroll-padding-top: 20px;
color-scheme: light dark;
}
html.prez {
font-size: 22px;
transform: scaleX(-1);
color-scheme: dark !important;
.markup-container {
code,
code pre {
font-size: 0.6rem;
}
}
}
@media (min-width: 700px) {
html {
font-size: calc(var(--font-size-base) * 1.05);
}
}
@media (min-width: 950px) {
html {
font-size: calc(var(--font-size-base) * 1.12);
}
}
body {
line-height: var(--line-height);
}
html[data-theme="light"] {
color-scheme: light;
}
html[data-theme="dark"] {
color-scheme: dark;
}
abbr {
text-decoration: underline;
text-decoration-thickness: var(--text-decoration-thickness);
text-decoration-style: dashed;
cursor: help;
}
a {
color: var(--link-color);
text-decoration-thickness: var(--text-decoration-thickness);
text-decoration-color: var(--text-decoration-color);
&:hover {
text-decoration: none;
}
}
h1 {
font-size: 1.5rem;
}
h2 {
font-size: 1.4rem;
}
.sublink {
display: inline-block;
padding: 0.4em;
font-size: 80%;
text-decoration: none;
color: light-dark(#333, #ccc);
&:before {
content: "» ";
}
&:hover {
text-decoration: underline;
}
&:hover {
color: var(--link-color);
}
}
h3 {
font-size: 1.3rem;
}
h4 {
font-size: 1.2rem;
}
h5 {
font-size: 1rem;
}
h6 {
font-size: 1rem;
}
hr {
margin: 1.2rem auto;
background: none;
color: var(--secondary-color);
}
math {
font-size: 1.12em;
}
.body-inner {
display: flex;
flex-direction: column;
align-items: stretch;
justify-content: stretch;
min-height: 100vh;
.content {
flex-grow: 1;
main {
min-height: 100%;
}
}
}
.button-row {
display: flex;
gap: 1em;
flex-wrap: wrap;
align-items: center;
justify-content: center;
}
.button {
font-family: var(--ui-font);
border-radius: var(--border-radius);
background: var(--accent-color);
padding: 0 1rem;
height: 36px;
text-decoration: none;
text-align: center;
vertical-align: middle;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.3s, transform 0.3s;
&,
&:visited {
color: white;
}
&,
&:hover {
text-decoration: none;
}
&:hover {
background: color-mix(in srgb, white 5%, var(--accent-color));
transform: scale(0.99);
}
&.disabled {
cursor: disabled;
background: #eaeaea;
}
&.secondary {
background: light-dark(
color-mix(in srgb, black 20%, var(--accent-color)),
color-mix(in srgb, black 35%, var(--accent-color))
);
}
&.large {
font-size: 1rem;
padding: 1.2rem 0.8rem;
img {
margin-right: 0.4em;
width: 1.4em;
height: 1.4em;
}
}
.label {
white-space: nowrap;
}
img {
margin-right: 0.7rem;
width: 1.2em;
height: 1.2em;
}
}
.medium-and-up {
display: none;
@include mixins.when-medium {
display: initial;
}
}
.bottom-nav {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
.reading-time,
.video-duration {
display: flex;
align-items: center;
gap: 0.2em;
-webkit-touch-callout: none;
-webkit-user-select: none;
abbr {
text-decoration: none;
text-underline: none;
}
}
.future-indicator,
.draft-indicator,
.ongoing-indicator,
.exclusive-indicator,
.early-access-indicator,
.complete-indicator, .video-indicator {
color: light-dark(white, white);
background: var(--accent-color);
border-radius: 1em;
padding: 0.1em 0.8em;
vertical-align: middle;
font-size: 0.7em;
font-weight: 500;
display: inline-block;
}
.ongoing-indicator {
background: var(--link-color);
}
.complete-indicator {
background: var(--link-color);
}
.exclusive-indicator, .early-access-indicator {
background: var(--exclusive-chip-bg-color);
color: var(--exclusive-chip-text-color);
}
.video-indicator {
background: #ff6b35;
}
main {
display: flex;
flex-direction: row;
justify-content: center;
align-items: flex-start;
> .table-of-contents menu {
display: none;
}
> * {
flex-basis: 300px;
flex-grow: 1;
flex-shrink: 100;
}
> .page-html {
flex-grow: 0;
flex-shrink: 1;
flex-basis: var(--page-width);
overflow: hidden;
padding: 0;
margin: 0;
min-height: calc(100vh - 150px);
box-shadow: 0 0 40px light-dark(#f4f4f4, #00000);
background: var(--page-html-bg);
border: 1px solid var(--border-color);
border-top: none;
border-bottom: none;
}
.page-html-padded {
padding-block: var(--page-padding-block);
padding-inline: var(--page-padding-inline);
.page-thumbnail-container.main-thumbnail {
max-width: calc(100% + 2 * var(--page-padding-inline));
width: calc(100% + 2 * var(--page-padding-inline));
margin-inline-start: calc(-1 * var(--page-padding-inline));
margin-block-start: calc(-1 * var(--page-padding-block) - 2px);
}
}
.table-of-contents {
font-size: .92rem;
font-family: var(--font-ui);
a {
color: inherit;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-display);
font-weight: 700;
padding-top: 0;
&,
a {
color: inherit;
}
}
h1 {
font-size: 1.15em;
}
h2 {
font-size: 1.12em;
}
h3,
h4,
h5,
h6 {
font-size: 1em;
}
a {
text-decoration: none;
}
menu {
font-size: inherit;
li {
list-style-type: none;
text-indent: none;
margin: 0;
padding: 0;
padding-inline: 0.4em;
line-height: 1.2;
color: light-dark(#1a1a1a, #f0f0f0);
border-left: 2px solid light-dark(#d9d9d9, #414141);
&.past {
border-color: var(--accent-color);
}
&:not(.reading):hover {
background: color-mix(in srgb, var(--accent-color) 20%, transparent);
border-color: color-mix(in srgb, var(--accent-color) 20%, transparent);
}
&.reading {
color: light-dark(#1a1a1a, #f0f0f0);
border-color: var(--accent-color);
background: var(--accent-color);
color: white;
position: relative;
}
a {
color: inherit;
text-decoration: none !important;
display: inline-block;
width: 100%;
padding-top: 0.4em;
padding-bottom: 0.4em;
}
&[data-level="3"] a {
padding-left: 0.5em;
}
&[data-level="4"] a {
padding-left: 1em;
}
&[data-level="5"] a {
padding-left: 1.5em;
}
&[data-level="6"] a {
padding-left: 2em;
}
}
}
}
}
@media (min-width: 950px) {
main {
> .table-of-contents {
min-width: 320px;
padding: 1em 2em;
flex-shrink: 1;
menu {
padding: 1em;
display: inline-block;
width: auto;
border-radius: var(--border-radius);
background: var(--page-html-bg);
border: 1px solid var(--border-color);
}
}
}
}
@media (min-width: 1400px) {
main {
> .table-of-contents {
min-width: 400px;
}
}
}
@media (min-width: 700px) {
.table-of-contents {
position: sticky;
top: 60px;
max-height: calc(100vh - 100px);
overflow-y: auto;
}
}
.series-nav {
padding-top: 0.4rem;
padding-bottom: 2.8rem;
.series-title {
font-weight: 200;
font-size: 1rem;
a {
font-weight: 350;
}
}
.series-circles {
font-family: var(--font-ui);
padding-top: 0.6rem;
display: flex;
flex-wrap: wrap;
flex-direction: row;
align-items: center;
gap: 0.15rem;
.series-circle {
font-size: 0.9rem;
font-weight: 600;
border-radius: 0.3rem;
width: 1.8rem;
height: 1.8rem;
display: flex;
align-items: center;
justify-content: center;
text-decoration: none;
h2 {
font-family: inherit;
font-size: inherit;
padding: 0;
margin: 0;
}
&.series-circle-past {
background: var(--link-color);
color: light-dark(#fafafa, #1a1a1a);
}
&.series-circle-current {
background: var(--link-color);
color: light-dark(#fafafa, #1a1a1a);
}
&.series-circle-future {
color: inherit;
background: light-dark(#f1f1f1, color-mix(in srgb, #2a2a2a 95%, white));
&:hover {
background: light-dark(#e5e5e5, #3a3a3a);
}
}
}
}
}
.nav-bottom {
background: var(--accent-color);
font-family: var(--font-ui);
font-size: 0.9rem;
padding: 2em 2em;
min-height: 150px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1.2em;
.nav-outlinks {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
gap: 1.4rem;
&.icons {
gap: 1.2em;
a {
display: flex;
flex-direction: row;
align-items: center;
}
.inline-icon-container {
svg {
--side: 2em;
width: var(--side);
height: var(--side);
vertical-align: middle;
fill: white;
}
margin-block: 0.4em;
margin-inline-end: 0.4em;
}
}
a {
color: white;
text-decoration: none;
transition: all 0.2s;
&:hover {
transform: scale(1.1) rotate(0.5deg);
}
}
}
}
.hide-when-small {
@include mixins.when-small {
display: none;
}
}
@keyframes loading-bounce {
0%,
100% {
transform: rotate(0deg);
}
40% {
transform: rotate(2deg);
}
60% {
transform: rotate(2deg);
}
80% {
transform: rotate(-2deg);
}
}
.inline-icon {
width: 0.92em;
height: 0.92em;
}
#page-topnav {
font-family: var(--font-ui);
height: var(--topnav-height);
z-index: 5;
padding: 0;
margin: 0;
}
img,
video {
max-width: 100%;
height: auto;
}
.modal {
z-index: 100;
}
media-player {
line-height: 0;
aspect-ratio: initial;
video {
height: 100%;
}
}
figure.code-block {
width: 100%;
}
.page-thumbnail-container {
pointer-events: none;
border-top: 1px solid rgba(255, 255, 255, 0.1);
margin-block-end: -4.1em;
position: relative;
display: inline-block;
overflow-x: hidden;
img {
mask-image: linear-gradient( to bottom, black 10%, transparent 92% );
-webkit-mask-image: linear-gradient( to bottom, black 10%, transparent 92% );
}
}
.page-thumbnail {
height: auto;
overflow: hidden;
display: block;
}
::target-text {
background-color: rgba(255, 217, 0, 0.4);
color: inherit;
outline: 2px solid rgba(255, 217, 0, 0.7);
border-radius: 2px;
padding: 0 2px;
@media (prefers-color-scheme: dark) {
background-color: rgba(255, 217, 0, 0.3);
outline: 2px solid rgba(255, 217, 0, 0.6);
}
}
.post-list {
.month-header {
font-family: var(--font-display);
font-size: 1.2em;
margin-bottom: 1em;
text-align: center;
}
}
.exclusive-star {
position: absolute;
z-index: 10;
--side: 3.4rem;
top: calc(var(--side) * -0.4);
right: calc(var(--side) * -0.4);
transition: all 0.2s;
@include mixins.when-small {
display: none;
}
img {
width: var(--side);
height: var(--side);
transform: scaleX(-1);
}
&:hover {
transform: scale(1.05) rotate(0.5deg);
}
}
.post-list-item {
--item-radius: 0.5rem;
border-radius: var(--item-radius);
padding: 1.25em 1.5em;
position: relative;
background: var(--secondary-bg);
border: 1px solid var(--border-color);
&.no-summary {
margin-bottom: 1.4em;
}
&.exclusive {
border: var(--border-width) solid var(--exclusive-border-color);
position: relative;
}
&.video {
display: flex;
flex-direction: column;
gap: 1em;
.video-embed {
width: 100%;
img {
border-radius: 8px;
width: 100%;
}
.video-thumb-link {
display: block;
position: relative;
.video-thumb-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.5em;
background: rgba(0,0,0,0.3);
border-radius: 8px;
transition: background 0.2s;
.play-icon {
font-size: 3em;
color: white;
text-shadow: 0 2px 10px rgba(0,0,0,0.5);
}
.silver-badge {
background: linear-gradient(135deg, #c0c0c0, #a0a0a0);
color: #333;
padding: 0.3em 0.8em;
border-radius: 4px;
font-size: 0.9em;
font-weight: bold;
}
}
&:hover .video-thumb-overlay {
background: rgba(0,0,0,0.5);
}
}
}
.post-list-item-inner {
width: 100%;
}
}
@media (max-width: 699px) {
border-left: none !important;
border-right: none !important;
border-bottom: none !important;
border-radius: 0;
margin-inline: calc(-1 * var(--page-padding-small));
margin-block-end: -0.4em;
background: transparent;
.page-thumbnail-container {
max-width: calc(100% + 2 * var(--page-padding-inline));
width: calc(100% + 2 * var(--page-padding-inline));
margin-inline: calc(-1 * var(--page-padding-inline));
border-radius: 0;
}
&:last-child {
margin-bottom: 1.4em;
}
.post-list-item-thumb {
border-radius: 0;
}
}
.post-link {
display: inline-block;
text-wrap: balance;
white-space: unset;
color: inherit;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
.post-list-thumb {
float: right;
margin-left: 1em;
margin-bottom: 0.5em;
width: 140px;
aspect-ratio: 16 / 9;
border-radius: 6px;
overflow: hidden;
flex-shrink: 0;
@media (max-width: 699px) {
display: none;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.2s;
}
&:hover img {
transform: scale(1.05);
}
}
.post-list-title {
font-family: var(--font-title);
font-weight: 700;
font-size: 1.5em;
line-height: 1.3;
margin: 0 0 0.5em 0;
b {
color: light-dark(#000, #000);
background: light-dark(#fffb94cc, #fff796f7);
padding: 0.1em 0.15em;
font-weight: bold;
border-radius: var(--border-radius);
}
}
.post-metadata {
font-family: var(--font-ui);
font-size: 0.85em;
opacity: 0.7;
color: var(--secondary-text-color);
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
gap: 0.75em;
margin-bottom: 0.75em;
padding-bottom: 0.75em;
border-bottom: 1px solid rgba(255,255,255,0.08);
}
.post-summary {
font-size: 0.95em;
line-height: 1.6;
opacity: 0.9;
&.snippet {
line-break: anywhere;
}
p {
margin-block: 0.5em;
}
p:first-child {
margin-top: 0;
}
p:last-child {
margin-bottom: 0;
}
ul li {
margin-left: 2em;
}
figure,
picture,
img,
video,
iframe,
figure,
.tip,
.youtube-embed,
h1,
h2,
h3,
h4,
h5,
h6,
.dialog,
.tip,
.recap,
blockquote,
.responsive-table
{
display: none !important;
}
b {
color: light-dark(#000, #000);
background: light-dark(#fffb94cc, #fff796f7);
padding: 0.14em 0.18em;
font-weight: bold;
border-radius: var(--border-radius);
padding: 0.25em 0.375em;
}
}
.read-more {
font-family: var(--font-ui);
font-size: 0.9em;
margin-top: 1em;
a {
color: var(--ftl-blue);
text-decoration: none;
font-weight: 500;
&::after {
content: " →";
transition: transform 0.2s;
display: inline-block;
}
&:hover {
text-decoration: underline;
&::after {
transform: translateX(3px);
}
}
}
}
}
.post-block-link {
color: inherit;
text-decoration: inherit;
}
.post-summary.snippet {
white-space: pre;
}
.pagination {
--pagination-color: var(--accent-color);
background: var(--pagination-color);
color: white;
border-radius: var(--border-radius);
font-size: 1rem;
margin: 2em auto;
margin-bottom: 2rem;
display: flex;
align-items: center;
.pagination-section {
font-family: var(--font-ui);
font-size: 0.8rem;
flex-grow: 1;
display: flex;
flex-basis: 33%;
justify-content: center;
align-items: center;
> * {
color: white;
padding: 0.4em 0.8em;
text-decoration: none;
}
&:first-child {
justify-content: flex-start;
a {
border-right: 1px solid rgba(255, 255, 255, 0.4);
}
}
&:last-child {
justify-content: flex-end;
a {
border-left: 1px solid rgba(255, 255, 255, 0.4);
}
}
}
}
img, video {
height: auto;
}
.markup-container {
font-size: var(--text-font-size);
font-weight: 400;
--figure-width: min(93%, 50rem);
--dialog-width: min(93%, 40rem);
--paragraph-block-start: 0.4em;
--paragraph-block-end: 1.2em;
--figure-block-margin: 1.8em;
font-weight: 400;
overflow-x: hidden;
&.figure-caption {
--paragraph-block-end: 0.2em;
}
p, ul, blockquote {
margin-block-start: var(--paragraph-block-start);
margin-block-end: var(--paragraph-block-end);
}
div {
h1, h2, h3, h4, h5, h6 {
&:first-child {
margin-block-start: 0;
}
}
}
blockquote p:last-child {
margin-block-end: 0;
}
ul p {
margin-block-end: 0.4rem;
}
a:first-child {
> h1, h2, h3, h4, h5, h6 {
margin-block-start: 0em !important;
}
}
p {
[data-kind="media"],
[data-kind="diagram"] {
display: block;
height: auto;
max-width: var(--figure-width);
margin-inline: auto;
margin-block: var(--figure-block-margin);
overflow: hidden;
&.transparent-for-dark {
@media (prefers-color-scheme: light) {
background: #111;
}
}
}
> math[display="block"] {
max-width: var(--figure-width);
margin-inline: auto;
margin-block: var(--figure-block-margin);
font-size: 1.22em;
}
}
.svelte-component {
margin-block: var(--figure-block-margin);
font-family: var(--font-ui);
font-size: 1rem;
svg {
filter: none !important;
}
h1, h2, h3, h4, h5, h6 {
&:first-child {
margin-block-start: 0em !important;
}
}
}
.post-list-item {
margin-block-end: 1.4em;
}
/* tables */
.responsive-table {
overflow-x: auto;
max-width: var(--figure-width);
margin-inline: auto;
margin-block: var(--figure-block-margin);
table {
width: auto;
margin: 0 auto;
}
}
> .disclosure {
font-family: var(--font-ui);
font-size: var(--ui-font-size);
padding: .4em .8em;
border: 1px dashed var(--border-color);
border-radius: var(--border-radius);
margin-inline: auto;
margin-block: var(--figure-block-margin);
p {
margin: 0;
}
}
> .playwall {
position: relative;
margin-inline: auto;
margin-block: var(--figure-block-margin);
max-width: 600px;
border: 1px solid var(--exclusive-border-color);
border-radius: 8px;
padding: 0.8em 1.2em;
h1 {
padding-block-start: 0;
margin-block-start: 0;
}
}
a.anchor {
text-decoration: none;
color: light-dark(var(--p-black), var(--p-white));
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: var(--font-title);
font-weight: 900;
text-wrap: balance;
}
h1 {
font-size: 2.7rem;
margin-block-start: 0em;
margin-block-end: 0em;
font-weight: 250;
}
h2 {
font-size: 1.72rem;
margin-block-start: 1.6em;
margin-block-end: 0.32em;
}
h3 {
font-size: 1.5rem;
margin-block-start: 1.4em;
margin-block-end: 0.24em;
font-weight: 630;
}
h4 {
font-size: 1.1rem;
margin-block-start: .4em;
margin-block-end: 0.16em;
font-weight: 630;
}
h5 {
font-size: 1rem;
margin-block-start: .4em;
margin-block-end: 0.08em;
font-weight: 630;
}
h6 {
font-size: 1rem;
margin-block-start: .4em;
margin-block-end: 0.04em;
font-weight: 630;
}
a:not(.anchor):not([role="button"]) {
transition: 0.17s;
transition-property: background, box-shadow, color, display, text-decoration-thickness;
&:focus-within {
outline: none;
text-decoration: underline;
text-decoration-thickness: var(--text-decoration-thickness);
}
}
ul ul {
margin-block-end: 0;
}
ul li,
ol li {
margin-inline-start: 2rem;
line-height: 1.6;
}
/* UI elements */
.page-title {
font-weight: 700;
line-height: 1.2;
padding-block-start: 0;
font-size: 2.6rem;
padding: 1.4rem 0;
padding-block-end: .4rem;
&.has-series {
padding-block-end: 0.8rem;
}
}
.page-metadata {
font-family: var(--font-ui);
font-size: 1rem;
color: var(--secondary-text-color);
line-height: 100%;
font-weight: 400;
padding: 0.2em 0;
margin-block-end: 1.8em;
light-dark(color-mix(in srgb, #000 0%, white 98%), color-mix(in srgb, #000 80%, white));
box-shadow: 0 0 4px transparent;
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 1em;
&:hover {
text-shadow: none;
}
.author-attribution {
display: flex;
gap: 0.4em;
align-items: center;
picture img {
width: 1.4em;
height: 1.4em;
}
}
}
.reddit-button-container,
.youtube-button-container {
display: flex;
justify-content: center;
.inline-icon-container {
margin-inline-end: 0.8rem;
}
}
/* figures */
figure {
max-width: var(--figure-width);
display: flex;
flex-direction: column;
align-items: center; /* Centers the caption with the image */
width: fit-content;
margin-inline: auto;
margin-block: var(--figure-block-margin);
@include mixins.when-small {
max-width: 100%;
}
&.code-block {
--code-border-color: var(--border-color);
&,
code {
border-radius: var(--border-radius);
font-size: var(--code-font-size);
}
code {
padding: 0.6em 0.8em;
}
}
&:not(.code-block) {
border: 1px solid var(--border-color);
border-radius: 6.9px;
padding: .8em;
@media (max-width: 1199px) {
max-width: 95%;
}
@media (max-width: 699px) {
max-width: 100%;
}
video,
img,
embed {
max-width: 100%;
height: auto;
display: block;
margin: auto;
}
figcaption {
align-self: stretch;
max-width: min-content;
min-width: 100%;
margin-inline: auto;
margin-block: 0em;
padding-block-start: 0.4em;
padding-inline: 0em;
.markup-container, cite {
font-family: var(--font-ui);
font-size: var(--ui-font-size);
}
cite {
opacity: .8;
font-style: normal;
a {
text-decoration: none;
color: inherit;
&:hover {
text-decoration: underline;
}
&:before {
content: "→ ";
}
}
}
}
}
}
/* footnotes */
.footnote-definition {
.footnote-definition-label {
float: left;
}
text-indent: 1rem;
}
.youtube-embed {
background: black;
position: relative;
aspect-ratio: 16/9;
margin-block-end: 1rem;
iframe {
position: absolute;
inset-block-start: 0;
inset-inline-start: 0;
width: 100%;
height: 100%;
border: 0;
}
}
/* tables */
table {
margin-block-end: 2rem;
width: 100%;
border: 1px solid light-dark(#e5e5e5, #3a3a3a);
border-collapse: collapse;
font-size: 90%;
}
td,
th {
padding: 0.25rem 0.5rem;
border: 1px solid light-dark(#e5e5e5, #3a3a3a);
}
tbody tr:nth-child(odd) {
td,
th {
background-color: light-dark(#f7f7f7, #1a1a1a);
}
}
strong {
font-weight: 650;
}
.asciicast {
text-align: center;
margin: 20px auto !important;
}
ul,
ol {
li {
margin-block-end: 0.4rem;
}
}
code {
font-family: var(--font-code);
}
code:not(.scroll-wrapper) {
vertical-align: 0em;
font-size: var(--font-inline-code-size);
}
.dialog {
margin-block: var(--figure-block-margin);
margin-inline-start: auto;
margin-inline-end: auto;
font-size: var(--ui-font-size);
display: flex;
flex-direction: row;
overflow: hidden;
.dialog-head {
align-self: flex-start;
--head-side: 4.2em;
flex-basis: var(--head-side);
width: var(--head-side);
height: var(--head-side);
margin: 0rem 0.4rem;
flex-shrink: 0;
img,
embed,
svg {
width: 100%;
height: auto;
}
&.round {
img,
embed,
svg {
border-radius: 50%;
}
}
}
.dialog-text {
--paragraph-block-end: .4em;
max-width: var(--dialog-width);
align-self: flex-start;
border-radius: 0.8em;
padding-inline: 0.9em;
padding-block: 0.2em;
overflow: hidden;
font-family: var(--font-ui);
font-weight: 400;
background-color: var(--bubble-color);
color: var(--text-color);
@media (prefers-color-scheme: light) {
--bubble-color: oklch(93.46% 0.0187 256.35);
--text-color: oklch(26.03% 0 0);
}
@media (prefers-color-scheme: dark) {
--bubble-color: oklch(0.35 0.02 67.46);
--text-color: oklch(99% 0 0);
}
&, p, ul, blockquote {
font-size: 1em;
}
h1, h2, h3, h4, h5, h6 {
margin-block-start: .4em;
}
.full-width,
.code-block {
max-width: 100%;
code {
border: none !important;
}
}
}
&.right {
flex-direction: row-reverse;
.dialog-text {
--bubble-color: oklch(62.44% 0.2054 255.56);
--text-color: oklch(0.98 0 0);
color-scheme: dark;
--link-color: oklch(97.89% 0 32.16);
--text-decoration-color: oklch(97.89% 0 32.16);
}
}
}
.tip,
.recap {
font-size: 0.89em;
max-width: var(--dialog-width);
padding: 0.3em 0.8em;
border-radius: var(--border-radius);
border: 1px solid var(--border-color);
margin-inline: auto;
margin-block: var(--figure-block-margin);
.full-width {
max-width: 100%;
}
.tip-header {
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
margin-block-start: 0.2rem;
margin-block-end: 0.2rem;
font-family: var(--font-title);
font-size: 1.1em;
img {
--side: 2.4em;
margin-inline-start: 0;
transform: none;
margin-inline-end: 0.5rem;
width: var(--side);
height: var(--side);
}
}
p,
ul {
&:last-child {
margin-block-end: 0;
}
}
}
blockquote {
max-width: var(--dialog-width);
width: auto;
margin-inline: auto;
margin-block: var(--figure-block-margin);
text-wrap: balance;
font-size: 0.89em;
padding: 0.6em 1em;
color: inherit;
background: light-dark(rgba(251, 251, 251, 0.5), rgba(37, 35, 35, 0.5));
border: 10px solid var(--accent-color);
border-left-width: 2px;
border-top-width: 2px;
clip-path: polygon( 0 0, calc(100% - 12px) calc(-2 * 2px), calc(100% + 2px) 12px, 100% 100%, 12px 100%, calc(-2 * 2px) calc(100% - 12px), 0 0 );
}
.small {
font-size: 1.2rem;
}
span.local-datetime {
font-weight: bold;
}
.sponsor-list {
line-height: 1.6;
font-size: 1rem;
font-family: var(--font-ui);
margin-block: var(--figure-block-margin);
}
.patreon-plug {
padding-block-start: 1rem;
display: flex;
flex-direction: column;
align-items: center;
font-size: 1.3rem;
@include mixins.when-small {
font-size: 1rem;
}
}
svg,
img[src$=".svg"],
embed[src$=".svg"] {
&[title$="for-dark"] {
filter: invert(87%) hue-rotate(180deg);
}
&:not([title$="for-dark"]) {
filter: none;
}
@media (prefers-color-scheme: dark) {
&[title$="for-dark"] {
filter: none;
}
&:not([title$="for-dark"]) {
filter: invert(87%) hue-rotate(180deg);
}
}
}
}
.markup-container,
.disclosure,
.playwall,
blockquote {
> :last-child {
&.code-block {
margin-block-end: 0.6em !important;
}
}
}
img.float-left {
float: left;
margin-inline-end: 1em;
}
@keyframes grow {
0% { transform: scale(1); }
80% { transform: scale(1); }
90% { transform: scale(1.01) rotate(-1deg); }
100% { transform: scale(1); }
}
/* For the animated border: */
@keyframes job-ad-border {
0% {
border-image: linear-gradient(120deg, #88f, #8fc 40%, #f8f 60%, #88f) 1;
}
25% {
border-image: linear-gradient(160deg, #f8f, #88f 40%, #8fc 60%, #f8f) 1;
}
50% {
border-image: linear-gradient(210deg, #8fc, #f8f 40%, #88f 60%, #8fc) 1;
}
75% {
border-image: linear-gradient(260deg, #f8f, #8fc 40%, #88f 60%, #f8f) 1;
}
100% {
border-image: linear-gradient(120deg, #88f, #8fc 40%, #f8f 60%, #88f) 1;
}
}
.champion-plug {
font-family: var(--font-ui);
font-size: var(--ui-font-size);
margin-bottom: 1.4em;
padding: 1.2em 1.5em;
border: 1px solid light-dark(#e5e5e5, #3a3a3a);
border-radius: var(--border-radius);
background: light-dark(rgba(251, 251, 251, 0.6), rgba(37, 35, 35, 0.6));
max-width: var(--figure-width);
margin-inline: auto;
margin-block: var(--figure-block-margin);
.champion-content {
display: flex;
align-items: center;
gap: 1.2em;
@include mixins.when-small {
flex-direction: column;
text-align: center;
gap: 0.8em;
}
}
.champion-logo {
flex-shrink: 0;
a {
display: block;
text-decoration: none;
}
.champion-logo-img {
max-height: 80px;
max-width: 160px;
height: auto;
width: auto;
object-fit: contain;
@include mixins.when-small {
max-height: 70px;
max-width: 140px;
}
}
}
.champion-text {
flex: 1;
line-height: 1.5;
.champion-sponsor-label {
font-size: 0.95em;
color: light-dark(#666, #aaa);
margin-bottom: 0.4em;
a {
color: inherit;
text-decoration: none;
font-weight: 600;
color: light-dark(#333, #ddd);
&:hover {
text-decoration: underline;
}
}
}
.champion-tagline {
font-size: 0.9em;
color: light-dark(#777, #999);
font-style: italic;
margin-bottom: 0.6em;
a {
color: inherit;
text-decoration: none;
transition: color 0.2s ease;
&:hover {
color: light-dark(#333, #ddd);
text-decoration: underline;
}
}
}
.champion-cta {
margin-top: 0.6em;
display: flex;
align-items: center;
gap: 0.8em;
.champion-cta-button {
display: inline-block;
padding: 0.4em 0.8em;
background: light-dark(#007acc, #135479);
color: white;
text-decoration: none;
border-radius: 4px;
font-size: 0.85em;
font-weight: 600;
transition: all 0.2s ease;
border: none;
&:hover {
transform: translateY(-1px);
// Default hover colors when no custom styling
&:not([style*="background:"]) {
background: light-dark(#005999, #3a8bb8);
box-shadow: 0 2px 8px rgba(0, 122, 204, 0.3);
}
// When custom background is set, darken it on hover
&[style*="background:"] {
filter: brightness(0.9);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}
}
&:active {
transform: translateY(0);
}
}
.champion-policy {
font-size: 0.85em;
color: light-dark(#666, #aaa);
a {
color: inherit;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
}
}
}
.dual-feature-plug {
font-family: var(--font-ui);
font-size: var(--ui-font-size);
max-width: var(--figure-width);
margin-inline: auto;
margin-block: var(--figure-block-margin);
padding: 1.2em 1.5em;
border: 1px solid light-dark(#e5e5e5, #3a3a3a);
border-radius: var(--border-radius);
background: light-dark(rgba(245, 248, 251, 0.6), rgba(35, 37, 42, 0.6));
.dual-feature-content {
p {
font-size: 0.95em;
color: light-dark(#666, #aaa);
margin-block: 0;
a {
color: inherit;
text-decoration: none;
font-weight: 600;
color: light-dark(#333, #ddd);
&:hover {
text-decoration: underline;
}
}
}
.video-container {
margin-top: 1em;
}
.dual-feature-video-button {
display: inline-flex;
align-items: center;
gap: 0.3em;
padding: 0.3em 0.6em;
background: light-dark(#eb0707, #c31414);
color: white;
text-decoration: none;
border-radius: 4px;
font-size: 0.85em;
font-weight: 600;
transition: all 0.2s ease;
margin-left: 0.4em;
svg {
width: 16px;
height: 16px;
fill: currentColor;
filter: none !important;
}
&:hover {
background: light-dark(
color-mix(in srgb, #e52e2e, black 10%),
color-mix(in srgb, #d4372c, black 10%)
);
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(255, 107, 53, 0.3);
text-decoration: none;
}
&:active {
transform: translateY(0);
}
}
}
}
aside {
max-width: var(--figure-width);
margin-inline: auto;
margin-block: var(--figure-block-margin);
font-family: var(--font-ui);
font-size: var(--ui-font-size);
border: 1px solid var(--border-color);
padding: 1.2em 1.6em;
border-radius: var(--border-radius);
}
.job-ad {
margin-bottom: 1.4em;
/* Animated border effect */
position: relative;
border: 4px solid;
border-image: linear-gradient(120deg, #88f, #8fc 40%, #f8f 60%, #88f) 1;
animation: job-ad-border 3s linear infinite;
border-color: #88f;
animation: grow 2s linear infinite;
background: light-dark(black, white);
color: light-dark(white, black);
padding: 2em;
display: flex;
flex-direction: row;
align-items: center;
gap: 2em;
p {
margin-block-end: 1.2em;
&:last-child {
margin-block-end: 0;
}
}
> :last-child {
flex-basis: 30%;
transform: scaleX(-100%);
}
}
:root {
--code-border-color: transparent;
--code-bg-color: light-dark(#f1f1f1, #292522);
--code-bg-color-dark: #292522;
}
/* Arborium theme variables: Melange Light & Dark */
:root {
--arb-at-light: #bc5c00;
--arb-co-light: #904180;
--arb-cb-light: #904180;
--arb-fb-light: #465aa4;
--arb-f-light: #465aa4;
--arb-fm-light: #465aa4;
--arb-k-light: #bc5c00;
--arb-kc-light: #bc5c00;
--arb-ko-light: #bc5c00;
--arb-kd-light: #bc5c00;
--arb-ke-light: #bc5c00;
--arb-kf-light: #bc5c00;
--arb-ki-light: #bc5c00;
--arb-kp-light: #bc5c00;
--arb-kr-light: #bc5c00;
--arb-kt-light: #bc5c00;
--arb-ky-light: #bc5c00;
--arb-o-light: #bc5c00;
--arb-pr-light: #bc5c00;
--arb-p-light: #54433a;
--arb-pb-light: #54433a;
--arb-pd-light: #54433a;
--arb-ps-light: #904180;
--arb-s-light: #3a684a;
--arb-ss-light: #bf0021;
--arb-tg-light: #bc5c00;
--arb-td-light: #bc5c00;
--arb-te-light: #bc5c00;
--arb-t-light: #bc5c00;
--arb-tb-light: #bc5c00;
--arb-tq-light: #bc5c00;
--arb-v-light: #54433a;
--arb-vb-light: #bf0021;
--arb-vp-light: #bc5c00;
--arb-c-light: #7d6658;
--arb-c-light-style: italic;
--arb-cd-light: #7d6658;
--arb-cd-light-style: italic;
--arb-m-light: #465aa4;
--arb-l-light: #904180;
--arb-da-light: #3a684a;
--arb-dd-light: #bf0021;
--arb-n-light: #904180;
--arb-tl-light: #54433a;
--arb-em-light-style: italic;
--arb-st-light-weight: bold;
--arb-tu-light: #465aa4;
--arb-tu-light-decoration: underline;
--arb-tr-light: #465aa4;
--arb-se-light: #a06d00;
--arb-tt-light: #bc5c00;
--arb-tt-light-weight: bold;
--arb-tx-light-decoration: line-through;
--arb-sp-light: #54433a;
--arb-in-light: #bc5c00;
--arb-sc-light: #bc5c00;
--arb-rp-light: #bc5c00;
--arb-cn-light: #bc5c00;
--arb-ex-light: #bc5c00;
--arb-pp-light: #bc5c00;
--arb-ch-light: #3a684a;
--arb-cs-light: #3a684a;
--arb-vm-light: #54433a;
--arb-fd-light: #465aa4;
--arb-tf-light: #bc5c00;
--arb-fc-light: #465aa4;
--arb-km-light: #bc5c00;
--arb-dr-light: #bc5c00;
--arb-rx-light: #3a684a;
--arb-at-dark: #c1a78e;
--arb-co-dark: #cf9bc2;
--arb-cb-dark: #cf9bc2;
--arb-fb-dark: #a3a9ce;
--arb-f-dark: #a3a9ce;
--arb-fm-dark: #a3a9ce;
--arb-k-dark: #bd8183;
--arb-kc-dark: #bd8183;
--arb-ko-dark: #bd8183;
--arb-kd-dark: #bd8183;
--arb-ke-dark: #bd8183;
--arb-kf-dark: #bd8183;
--arb-ki-dark: #bd8183;
--arb-kp-dark: #bd8183;
--arb-kr-dark: #bd8183;
--arb-kt-dark: #bd8183;
--arb-ky-dark: #bd8183;
--arb-o-dark: #bd8183;
--arb-pr-dark: #c1a78e;
--arb-p-dark: #ece1d7;
--arb-pb-dark: #ece1d7;
--arb-pd-dark: #ece1d7;
--arb-ps-dark: #cf9bc2;
--arb-s-dark: #85b695;
--arb-ss-dark: #d47766;
--arb-tg-dark: #bd8183;
--arb-td-dark: #bd8183;
--arb-te-dark: #bd8183;
--arb-t-dark: #c1a78e;
--arb-tb-dark: #c1a78e;
--arb-tq-dark: #c1a78e;
--arb-v-dark: #ece1d7;
--arb-vb-dark: #d47766;
--arb-vp-dark: #c1a78e;
--arb-c-dark: #867462;
--arb-c-dark-style: italic;
--arb-cd-dark: #867462;
--arb-cd-dark-style: italic;
--arb-m-dark: #a3a9ce;
--arb-l-dark: #cf9bc2;
--arb-da-dark: #85b695;
--arb-dd-dark: #d47766;
--arb-n-dark: #cf9bc2;
--arb-tl-dark: #ece1d7;
--arb-em-dark-style: italic;
--arb-st-dark-weight: bold;
--arb-tu-dark: #a3a9ce;
--arb-tu-dark-decoration: underline;
--arb-tr-dark: #a3a9ce;
--arb-se-dark: #ebc06d;
--arb-tt-dark: #c1a78e;
--arb-tt-dark-weight: bold;
--arb-tx-dark-decoration: line-through;
--arb-sp-dark: #ece1d7;
--arb-in-dark: #bd8183;
--arb-sc-dark: #bd8183;
--arb-rp-dark: #bd8183;
--arb-cn-dark: #bd8183;
--arb-ex-dark: #bd8183;
--arb-pp-dark: #bd8183;
--arb-ch-dark: #85b695;
--arb-cs-dark: #85b695;
--arb-vm-dark: #ece1d7;
--arb-fd-dark: #a3a9ce;
--arb-tf-dark: #c1a78e;
--arb-fc-dark: #a3a9ce;
--arb-km-dark: #bd8183;
--arb-dr-dark: #bd8183;
--arb-rx-dark: #85b695;
}
$arb-tokens: at, co, cb, cr, fb, f, fm, k, kc, ko, kd, ke, kf, ki, kp, kr, kt, ky, o, pr, p, pb, pd, ps, s, ss, tg, td, te, t, tb, tq, v, vb, vp, c, cd, m, l, da, dd, n, tl, em, st, tu, tr, se, tt, tx, sp, eb, er, ns, in, sc, rp, cn, ex, pp, ch, cs, vm, fd, tf, fc, km, dr, rx;
@mixin arborium-mode($mode) {
@each $token in $arb-tokens {
a-#{$token} {
color: var(--arb-#{$token}-#{$mode});
font-weight: var(--arb-#{$token}-#{$mode}-weight, normal);
font-style: var(--arb-#{$token}-#{$mode}-style, normal);
text-decoration: var(--arb-#{$token}-#{$mode}-decoration, none);
}
}
}
code.scroll-wrapper {
background: var(--code-bg-color);
border: 1px solid var(--code-border-color);
color: inherit;
}
/* Default: light */
@include arborium-mode("light");
/* System preference: dark */
@media (prefers-color-scheme: dark) {
@include arborium-mode("dark");
code.scroll-wrapper {
background: var(--code-bg-color-dark);
}
}
/* Explicit data-theme overrides */
:root[data-theme="light"] {
@include arborium-mode("light");
code.scroll-wrapper {
background: var(--code-bg-color);
}
}
:root[data-theme="dark"] {
@include arborium-mode("dark");
code.scroll-wrapper {
background: var(--code-bg-color-dark);
}
}
.youtube-thumbnail-link {
max-width: 80%;
margin-inline: auto;
margin-block: var(--figure-block-margin);
}
</style>
<script>
window.home = {
profile: null,
user_info: null,
viewer: {
"has_bronze": false,
"has_gold": false,
"has_silver": false,
"is_admin": false,
"tier_cause": null
},
sponsors: [
"Corey Alexander",
"Radu Matei",
"Ben Mitchell",
"Lena Schönburg",
"Chris Emery",
"old.woman.josiah",
"Sylvie Nightshade",
"Adam Gutglick",
"Zalán Bálint Lévai",
"Ahmad Alhashemi",
"Eugene Bulkin",
"Olivier Peyrusse",
"Justy",
"Guilherme Neubaner",
"Bob Ippolito",
"Scott Steele",
"Diego Roig",
"qrpth",
"Menno Finlay-Smits",
"playest",
"Sean Bryant",
"David Cornu",
"Romet Tagobert",
"Anna M",
"Blake Johnson",
"Brandon Piña",
"L0r3m1p5um",
"Vinay Mehta",
"SeniorMars",
"Luis",
"Tiziano Santoro",
"Chris Sims",
"Dominik Wagner",
"James Brown",
"Mark Tomlin",
"Elnath",
"Geoffrey Thomas",
"zed",
"Romain Kelifa",
"Berkus Decker",
"messense",
"Thehbadger",
"Kai Kaufman",
"Andrew Henshaw",
"Carson Page",
"C J Silverio",
"Alan O'Donnell",
"Pete LeVasseur",
"Senyo Simpson",
"Daniel Wagner-Hall",
"Marky Mark",
"ofrighil",
"Hadrien G.",
"Andronik",
"eliferrous",
"Lawrence Bethlenfalvy",
"Guillaume E",
"Matthias Zepper",
"Dragoon",
"Dimitri Merejkowsky",
"Vladimir",
"Laine Taffin Altman",
"0lach",
"Raphaël Thériault",
"Mark",
"Justin Smith",
"David White",
"Matěj Volf",
"Cole Tobin",
"Neil Blakey-Milner",
"Zoran Zaric",
"Matt Heise",
"Marc-Andre Giroux",
"Julian Schmid",
"Elendol",
"jatescher",
"Stephan Buys",
"Jim",
"Zeeger Lubsen",
"Taneli Kaivola",
"Sam Leonard",
"Kevin Murphy",
"Felix Weis",
"Josh Triplett",
"Michał Bartoszkiewicz",
"Marcin Kołodziej",
"AdrianEddy",
"Ronen Cohen",
"Urs Metz",
"Ryan",
"Horváth-Lázár Péter",
"Philipp Angerer",
"Mattia Valzelli",
"WeblWabl",
"ZacJW",
"Matthew T",
"Yann Schwartz",
"Antoine PESTEL-ROPARS",
"Andy Gocke",
"Steven Pham",
"Max Bruckner",
"Tomas Sedovic",
"Matt Jadczak",
"David Barsky",
"Christopher Valerio",
"Pete Bevin",
"Max von Forell",
"callym",
"Tobias Bahls",
"Philipp Hatt",
"Manuel Hutter",
"Enrico Zschemisch",
"Chris Biscardi",
"anichno",
"The0x539",
"Cole Kurkowski",
"Richard Pringle",
"Marcus Griep",
"Olivia Crain",
"Nyefan",
"Xirvik Servers",
"Tom Forbes",
"Arjen Laarhoven",
"Toon Willems",
"ShikChen",
"Borys Minaiev",
"Jelle Besseling",
"Egor Ternovoi",
"Romain Ruetschi",
"Sung Jeon",
"Geoffroy Couprie",
"Brooke Tilley",
"Jesse Luehrs",
"Tyler Bloom",
"Austin Traver",
"Mason Ginter",
"David Smith",
"Dom",
"compwhizii",
"xales",
"Mateusz Wykurz",
"Noel",
"Christian Bourjau",
"Aleksandre Khokhiashvili",
"notryanb",
"Mathew Haji",
"Alex Krantz",
"Alex Rudy",
"Em Sharnoff",
"pinkhatbeard",
"Nicholas",
"Antoine Boegli",
"Mark Old",
"Jack Duvall",
"Gorazd Brumen",
"Lyssieth",
"dataphract",
"Yufan Lou",
"bbutkovic",
"Ives van Hoorne",
"Mike English",
"genny",
"Michael",
"Samit Basu",
"Björn Marschollek",
"Nicolas Riebesel",
"Ross Williams",
"Dirkjan Ochtman",
"Wyatt Herkamp",
"Chris Walker",
"Jimmy Hartzell",
"Guy Waldman",
"Reto Trappitsch",
"Tanner Muro",
"avborhanian",
"Hamilton Chapman",
"Torben Clasen",
"Marie Janssen",
"James Rhodes",
"Aiden Scandella",
"jalciné",
"Zac Harrold",
"Michał Zalewski",
"René Ribaud",
"Nicolas Coulange",
"Johnathan Pagnutti",
"Kamran Khan",
"Mario Fleischhacker",
"Tabitha",
"Richard Stephens",
"Geoff Cant",
"Marcus Griep",
"Marty Penner",
"Matt Jackson",
"Yuriy Taraday",
"Ben Wishovich",
"Henrik Tudborg",
"Gioele Pannetto",
"Zachary Thomas",
"Vincent Mutolo",
"Mikkel Rasmussen",
"Braidon Whatley",
"Jan-Stefan Janetzky",
"Olly Swanson",
"hgranthorner",
"Dave Minter",
"Justin Ossevoort",
"Victor Song",
"Benjamin Röjder Delnavaz",
"Adam Lassek",
"Ripta Pasay",
"belzael",
"Isak Sunde Singh",
"Morgan Rosenkranz",
"Beat Scherrer",
"Peter Shih",
"Joshua Roesslein",
"Daniel Silverstone",
"Antoine Rouaze",
"Ronen Ulanovsky",
"Astrid",
"Miguel Raz Guzmán Macedo",
"Walther",
"Jake Demarest-Mays",
"Integer 32, LLC",
"Alexandra Østermark",
"Luke Yue",
"Angelo",
"Niels Abildgaard",
"Scott Sanderson",
"Raine Godmaire",
"Boris Dolgov",
"Matt Campbell",
"budrick",
"Max Heaton",
"Yves",
"Paul Marques Mota",
"Michal Hošna",
"Luke Konopka",
"villem",
"Valentin Mariette",
"prairiewolf",
"Jonathan Adams",
"DaVince",
"Zaki",
"Santiago Lema",
"Ian McLinden",
"Malik Bougacha",
"Twan Walpot",
"Marco Carmosino",
"James Leitch",
"Jörn Huxhorn",
"Andy F",
"Jean-David Gadina",
"Paige Ruten",
"Luuk",
"Seth",
"Christoph Grabo",
"Daniel Strittmatter",
"Paul Horn",
"Lucille Blumire",
"Dylan Anthony",
"milan",
"Colin VanDervoort",
"traxys",
"Simon Menke",
"clement",
"John VanEnk",
"Kyle Lacy",
"Timothée Gerber",
"Mathias Brossard",
"psentee",
"you got maiL",
"Xavier Groleau",
"me",
"Michael Alyn Miller",
"Chris Thackrey",
"std__mpa",
"Ivo Murrell",
"Brian L. Troutwine",
"Chris",
"Makoto Nakashima",
"Zachary Myers",
"Sawyer Knoblich"
]
};
</script>
<meta property="home:page-path" content="/content/_index.md"><!-- inserted by home -->
<script type="module" src="https://cdn.fasterthanli.me/dist/assets/bundle-BiGFyzsU.js" defer></script><link rel="stylesheet" href="https://cdn.fasterthanli.me/dist/assets/bundle-0LGoujCw.css" media="print" onload="this.media='all'"></head>
<body>
<div class="body-inner">
<div class="content">
<a id="home-page-top" href="#home-page-top"></a>
<main>
<div class="page-html-spacer"></div>
<div class="page-html">
<div id="page-topnav" class="page-topnav"></div>
<style>
.frontpage-hero {
display: flex;
flex-wrap: wrap;
gap: 2rem;
align-items: center;
padding: 2rem 0 3rem 0;
border-bottom: 1px solid rgba(255,255,255,0.1);
margin-bottom: 2rem;
}
.frontpage-hero-text {
flex: 1;
min-width: 280px;
}
.frontpage-hero-text p {
font-size: 1.15em;
line-height: 1.7;
margin-bottom: 1em;
}
.frontpage-hero-text p:last-child {
margin-bottom: 0;
}
.frontpage-hero-image {
flex: 0 0 auto;
}
.frontpage-hero-image img {
width: 180px;
height: 180px;
border-radius: 50%;
object-fit: cover;
border: 3px solid var(--ftl-blue);
box-shadow: 0 4px 20px rgba(88, 141, 222, 0.3);
}
@media (max-width: 600px) {
.frontpage-hero {
flex-direction: column-reverse;
text-align: center;
}
.frontpage-hero-image img {
width: 140px;
height: 140px;
}
}
.frontpage-section {
margin-bottom: 3rem;
}
.frontpage-section h2 {
font-family: var(--font-display);
font-size: 1.6em;
margin-bottom: 1.5rem;
}
.frontpage-section h2 .sublink {
font-size: 0.5em;
font-weight: normal;
margin-left: 1em;
opacity: 0.7;
}
.frontpage-section h2 .sublink:hover {
opacity: 1;
}
.frontpage-cta {
margin-top: 1.5rem;
padding: 1.2rem;
background: rgba(88, 141, 222, 0.1);
border-radius: 8px;
border-left: 3px solid var(--ftl-blue);
}
.frontpage-cta p {
margin: 0;
}
</style>
<div class="page-html-padded markup-container page-markup">
<div class="frontpage-hero">
<div class="frontpage-hero-text">
<p data-bo="86">Hi! I’m Amos, better known as <a href="/about">@fasterthanlime</a>.</p>
<p data-bo="144">I make <a href="/articles">articles</a> and <a href="/videos">videos</a> about how computers work. My content is
long-form, didactic and exploratory — and often an excuse to teach Rust!</p>
<p data-bo="311">I also co-host <a href="https://sdr-podcast.com">Self-Directed Research</a> with <a href="https://jamesmunns.com/">James</a>.</p>
<p data-bo="416">You can <a href="/about">read more about me</a>, if you insist.</p>
</div>
<div class="frontpage-hero-image">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/about/amos-cat~ae575cf42d1da617.w400.jxl 1x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/about/amos-cat~d27fe6d942a1b558.jxl 1x,https://cdn.fasterthanli.me/content/about/amos-cat~d27fe6d942a1b558.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/about/amos-cat~d0d367a3f76eb534.w400.avif 1x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/about/amos-cat~3393357c0942debc.avif 1x,https://cdn.fasterthanli.me/content/about/amos-cat~3393357c0942debc.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/about/amos-cat~7443554f9d77c6cf.w400.webp 1x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/about/amos-cat~62ddb8b87fd4ec07.webp 1x,https://cdn.fasterthanli.me/content/about/amos-cat~62ddb8b87fd4ec07.webp 2x"><img src="https://cdn.fasterthanli.me/content/about/amos-cat~d27fe6d942a1b558.jxl" loading="lazy" width="768" height="1024" data-kind="media" data-input-path="/content/about/amos-cat.jxl" alt="Amos with a cat"></picture>
</div>
</div>
<div class="frontpage-section">
<h2>
Feed
<a class="sublink" href="/articles">View all</a>
</h2>
<div class="post-list">
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/my-gift-to-the-rust-docs-team" rel="noopener">
My gift to the rustdoc team
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Dec 13, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
14 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/docs">#docs</a></span>
<span>·</span>
<span><a href="/tags/tree-sitter">#tree-sitter</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/my-gift-to-the-rust-docs-team" rel="noopener">
<div class="post-summary markup-container "><p data-bo="138">About two weeks ago I entered a discussion with the docs.rs team about,
basically, why we have to look at this:</p>
<p data-bo="251"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~2b51213d5080e49f.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~a02d3ed6405331c3.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~aae2486dd16622f8.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~90422bc81a3bae50.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~eb49252c206ebe40.jxl 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~eb49252c206ebe40.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~d4be62e07bbcfeb9.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~3ccc4eaf851fd7f9.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~31f05cfeabbb1816.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~c880f407070dec4f.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~246a726e3edb536e.avif 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~246a726e3edb536e.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~108d2cd88f7f82ed.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~db28f2a92f2ec608.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~2560bc7eefd9f111.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~2620f2eb578c2766.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~c8ad806e4a94f7fb.webp 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~c8ad806e4a94f7fb.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x~eb49252c206ebe40.jxl" loading="lazy" width="1083" height="750" data-kind="media" data-input-path="/content/articles/my-gift-to-the-rust-docs-team/docsrs-no-colors@2x.jxl" class="" title="" alt="My browser showing a docs.rs page for a crate that I published myself, which contains a lot of different code blocks with different languages but they're all white on black. It's sad.
"></picture></p><p data-bo="504">When we could be looking at this:</p>
<p data-bo="539"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~9b1deb8e99fb2682.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~27ccd79ae4035c0a.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~bd30aa29b5400eb0.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~e20e499d5e65834e.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~708d0f07e1265747.jxl 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~708d0f07e1265747.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~e3f1a432e9c668ba.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~3a4993aab8948d72.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~53e5fad71d3fc327.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~08073874f4cd098d.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~fc0a176cb0cca55d.avif 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~fc0a176cb0cca55d.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~467941c8faca5817.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~fb9d0efd7aea8f39.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~5ddf9c85ebaa74b0.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~a1a3796821a165a5.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~c3080fac6477bf93.webp 1x,https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~c3080fac6477bf93.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x~708d0f07e1265747.jxl" loading="lazy" width="1083" height="750" data-kind="media" data-input-path="/content/articles/my-gift-to-the-rust-docs-team/docsrs-yes-colors@2x.jxl" class="" title="" alt="My browser showing a docs.rs page for a crate that I published myself, which contains a lot of different code blocks with different languages. this time it's colored.
"></picture></p><p data-bo="776">And of course, as always, there are reasons why things are the way they are.
In an effort to understand those reasons, I opened a GitHub issue which resulted
in a <a href="https://github.com/rust-lang/docs.rs/issues/3040">short but productive</a> discussion.</p>
<p data-bo="1026">I walked away discouraged, and then decided to, reasons be damned, attack this
problem from three different angles.</p>
<a id="background" href="#background" class="anchor"></a>
<a id="problems" href="#problems" class="anchor"></a>
<a id="solutions" href="#solutions" class="anchor"></a>
<a id="arborium" href="#arborium" class="anchor"></a>
<a id="angle-1-just-include-this-script" href="#angle-1-just-include-this-script" class="anchor"></a>
<a id="angle-2-it-goes-in-the-rustdoc-hole" href="#angle-2-it-goes-in-the-rustdoc-hole" class="anchor"></a>
<a id="angle-3-only-in-the-backend" href="#angle-3-only-in-the-backend" class="anchor"></a>
<a id="post-mortem" href="#post-mortem" class="anchor"></a>
<a id="conclusion" href="#conclusion" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/my-gift-to-the-rust-docs-team" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~ff47a5b28f46e53c.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~7cf679490e671084.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~e85c4499c08ba542.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~672a78afda0cc482.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~267e391ce89c9d08.jxl 1x,https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~267e391ce89c9d08.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~c3f2d8b89e23d437.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~bd916ad3df44692f.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~9c3885dafe81d1e4.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~a016850c4b5b703a.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~d707204f22118a2d.avif 1x,https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~d707204f22118a2d.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~4ba9645f87a74535.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~4f5dbff02ca347e3.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~ceca6e929ecae6fc.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~7efa7a42d2529b0e.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~968a752b3c01b6cc.webp 1x,https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~968a752b3c01b6cc.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/does-dioxus-spark-joy/_thumb~267e391ce89c9d08.jxl" loading="lazy" width="3840" height="2160" data-kind="media" data-input-path="/content/articles/does-dioxus-spark-joy/_thumb.jxl" alt="Thumbnail for Does Dioxus spark joy?"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/does-dioxus-spark-joy" rel="noopener">
Does Dioxus spark joy?
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Nov 22, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
11 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/dioxus">#dioxus</a></span>
<span>·</span>
<span><a href="/tags/frontend">#frontend</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/does-dioxus-spark-joy" rel="noopener">
<div class="post-summary markup-container "><div data-bo="230" class="dialog right">
<div class="dialog-head" title="Amos says:">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~7e12af3470699bdc.w400.jxl 1x,https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~a0ea81dcadb8636e.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~d884997b42fbba49.w900.jxl 1x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~55a3477398fe0cb1.jxl 1x,https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~55a3477398fe0cb1.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~45a3cd0b732f5ccc.w400.avif 1x,https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~e48742392d184dda.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~eea766689482b5e8.w900.avif 1x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~b094ff3737f6454a.avif 1x,https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~b094ff3737f6454a.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~87fb82d4e532a923.w400.webp 1x,https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~b07c9412606c8946.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~181264732affc244.w900.webp 1x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~3a98ffaa495414b6.webp 1x,https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~3a98ffaa495414b6.webp 2x"><img src="https://cdn.fasterthanli.me/content/img/reimena/amos-neutral~55a3477398fe0cb1.jxl" loading="lazy" width="42" height="42" data-kind="media" data-input-path="/content/img/reimena/amos-neutral.jxl" alt="Amos"></picture>
</div>
<div class="dialog-text markup-container">
<p data-bo="246">Note: this article is adapted from a presentation I gave at a Rust Paris Meetup — that’s why
it sounds a little different than usual. Enjoy!</p>
</div>
</div><p data-bo="390">Good evening! Tonight, I will attempt to answer the question: Does
<a href="https://github.com/dioxuslabs/dioxus">Dioxus</a> spark joy? Or at the very least,
whimsy.</p>
<p data-bo="546">What’s Dioxus, you ask? It is first and foremost a name that is quote: “legally
not inspired by any Pokémon”.</p>
<a id="a-short-and-mostly-wrong-history-of-web-apps" href="#a-short-and-mostly-wrong-history-of-web-apps" class="anchor"></a>
<a id="a-practical-example" href="#a-practical-example" class="anchor"></a>
<a id="love-hate" href="#love-hate" class="anchor"></a>
<a id="does-dioxus-spark-joy" href="#does-dioxus-spark-joy" class="anchor"></a>
<a id="afterword" href="#afterword" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/does-dioxus-spark-joy" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~181b24cf5fe45cbd.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~4bbbd34b9ede9f05.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~74715fd69a93c1bc.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~c36d54677dfbfe76.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~aedd8abda4d3ed2b.jxl 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~aedd8abda4d3ed2b.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~d3602dd054bf832e.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~ae5d97b2b8e60865.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~66cd241304fc9db7.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~25f68d667a2ad26d.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~62a5f2e45739eba7.avif 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~62a5f2e45739eba7.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~b18a016e6395039a.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~1582be9f6b70111e.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~f0402f437a295161.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~67671093dc9ddab5.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~4e5cf44b713867dc.webp 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~4e5cf44b713867dc.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/_thumb~aedd8abda4d3ed2b.jxl" loading="lazy" width="3842" height="2162" data-kind="media" data-input-path="/content/articles/engineering-a-rust-optimization-quiz/_thumb.jxl" alt="Thumbnail for Engineering a Rust optimization quiz"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/engineering-a-rust-optimization-quiz" rel="noopener">
Engineering a Rust optimization quiz
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Nov 01, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
14 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/quiz">#quiz</a></span>
<span>·</span>
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/eurorust">#eurorust</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/engineering-a-rust-optimization-quiz" rel="noopener">
<div class="post-summary markup-container "><p data-bo="198">There are several Rust quizzes online, including one that’s literally called the
“Unfair Rust Quiz” at <a href="https://this.quiz.is.fckn.gay/">https://this.quiz.is.fckn.gay/</a>, but when I was given the
opportunity to record an episode of the <a href="https://sdr-podcast.com/">Self-Directed Research
podcast</a> live on the main stage of <a href="https://eurorust.eu/2025/">EuroRust
2025</a>, I thought I’d come up with something special.</p>
<figure
class="paragraph-like"
data-bo="576"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~ed108ab5e398e6fd.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~9093a2a7a70cc8e5.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~d7a48a7116058709.w900.jxl 1x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~478a86d3446281d7.jxl 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~478a86d3446281d7.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~aa7feff27338fbf1.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~90dd56ba49448e1b.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~f09872ca2f77e192.w900.avif 1x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~fed46df743b852f4.avif 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~fed46df743b852f4.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~08ad393242985292.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~ee23edc5aa00cc8d.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~c25e7d8684579398.w900.webp 1x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~58012d0f832f4c70.webp 1x,https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~58012d0f832f4c70.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x~478a86d3446281d7.jxl" loading="lazy" width="795" height="714" data-kind="media" data-input-path="/content/articles/engineering-a-rust-optimization-quiz/unfair-rust-quiz@2x.jxl" title="The unfair rust quiz really deserves its name. It is best passed with a knowledgeable friend by your side. " alt="Question Misc 6 of the unfair Rust quiz, about drop order. "></picture><figcaption><div class="markup-container figure-caption"><p>The unfair rust quiz really deserves its name. It is best passed with a knowledgeable friend by your side.</p>
</div></figcaption>
</figure>
<a id="coming-up-with-the-questions" href="#coming-up-with-the-questions" class="anchor"></a>
<a id="nih-syndrome-ppt" href="#nih-syndrome-ppt" class="anchor"></a>
<a id="server-side-shenanigans-and-room-codes" href="#server-side-shenanigans-and-room-codes" class="anchor"></a>
<a id="deploying-the-beast" href="#deploying-the-beast" class="anchor"></a>
<a id="d-2-starting-fights-at-a-paris-meetup" href="#d-2-starting-fights-at-a-paris-meetup" class="anchor"></a>
<a id="d-1-panic-mode-and-missing-explanations" href="#d-1-panic-mode-and-missing-explanations" class="anchor"></a>
<a id="day-of-github-oauth-and-swipe-gestures" href="#day-of-github-oauth-and-swipe-gestures" class="anchor"></a>
<a id="showtime" href="#showtime" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/engineering-a-rust-optimization-quiz" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~165b4152955d780b.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~12b1bae1366b3fb2.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~1771afd05ee0c97d.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~c3c0bb3a2b41c0c9.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~9352f21b4484b883.jxl 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~9352f21b4484b883.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~0077be047d3f4524.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~c68e46067afa36df.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~0c20d46894fda257.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~7825d9065baf895b.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~aea38ba11c346bcd.avif 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~aea38ba11c346bcd.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~f5456980c6240de6.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~0f900dd23f27c98a.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~3815686ee25110d9.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~05101b93a5e2d26a.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~08fb0b6464945083.webp 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~08fb0b6464945083.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/_thumb~9352f21b4484b883.jxl" loading="lazy" width="2200" height="1264" data-kind="media" data-input-path="/content/articles/making-our-own-spectrogram/_thumb.jxl" alt="Thumbnail for Making our own spectrogram"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/making-our-own-spectrogram" rel="noopener">
Making our own spectrogram
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Sep 15, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
20 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/sound">#sound</a></span>
<span>·</span>
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/maths">#maths</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/making-our-own-spectrogram" rel="noopener">
<div class="post-summary markup-container "><p data-bo="251">A couple months ago <a href="/articles/the-science-of-loudness">I made a loudness meter</a>
and went way too in-depth into how humans have measured loudness over time.</p>
<p data-bo="409"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~83011aa317956c90.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~afea7ab87cdb0d3f.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~183d2ded1d67416a.w900.jxl 1x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~d5e6b54e3ade21f5.jxl 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~d5e6b54e3ade21f5.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~816fc9f55dd14a52.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~26770327a4ceaf2c.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~be2cf2c157a31891.w900.avif 1x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~93c9325ad8ad55a3.avif 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~93c9325ad8ad55a3.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~c42c1310f17eb713.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~64ed1b3feeb6f6d3.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~13a8a3896d7c6881.w900.webp 1x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~23be1cc4f4574700.webp 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~23be1cc4f4574700.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x~d5e6b54e3ade21f5.jxl" loading="lazy" width="800" height="512" data-kind="media" data-input-path="/content/articles/making-our-own-spectrogram/fasterthanlime-audio-meter@2x.jxl" class="" title="" alt="A screenshot of the fasterthanlime audio meter, with RMS, sample peak, true peak, and various loudness metrics.
"></picture></p><p data-bo="600">Today we’re looking at a spectrogram visualization I made, which is a lot more entertaining!</p>
<p data-bo="694"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~bfdf5332bac1c4c4.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~03877fa1fba54fec.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~eadeb08efadadc5c.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~1524786a02c13b76.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~c22af608785d58b2.jxl 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~c22af608785d58b2.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~d96983639bdbfe10.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~b7e95b9e54f9f2cd.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~7ea414d9dfd2cc5b.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~2f742d7c1339e1f1.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~12c9a6d75574bcc5.avif 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~12c9a6d75574bcc5.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~0f38fae704871a33.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~ac8675f3843dc5b7.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~2854399479c75822.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~fca0532957b2cf6c.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~8fe32b7d298a0aaa.webp 1x,https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~8fe32b7d298a0aaa.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x~c22af608785d58b2.jxl" loading="lazy" width="1100" height="632" data-kind="media" data-input-path="/content/articles/making-our-own-spectrogram/spectrogram-sonata-op25-3@2x.jxl" class="" title="" alt=""></picture></p><p data-bo="753">We’re going to talk about how to extract frequencies from sound waves, but also
how my spectrogram app is assembled from different Rust crates, how it
handles audio and graphics threads, how it draws the spectrogram etc.</p>
<a id="the-humble-sine-wave" href="#the-humble-sine-wave" class="anchor"></a>
<a id="approximating-a-square-wave" href="#approximating-a-square-wave" class="anchor"></a>
<a id="a-real-world-sample" href="#a-real-world-sample" class="anchor"></a>
<a id="chunking-and-windowing" href="#chunking-and-windowing" class="anchor"></a>
<a id="the-gabor-limit" href="#the-gabor-limit" class="anchor"></a>
<a id="interpolation" href="#interpolation" class="anchor"></a>
<a id="color-mapping" href="#color-mapping" class="anchor"></a>
<a id="frequency-mapping" href="#frequency-mapping" class="anchor"></a>
<a id="audio-input" href="#audio-input" class="anchor"></a>
<a id="drawing-the-ui" href="#drawing-the-ui" class="anchor"></a>
<a id="updating-the-texture" href="#updating-the-texture" class="anchor"></a>
<a id="profiling-my-program" href="#profiling-my-program" class="anchor"></a>
<a id="having-fun" href="#having-fun" class="anchor"></a>
<a id="closing-words" href="#closing-words" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/making-our-own-spectrogram" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~4b2ca00e0d443e0a.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~e2d4a79e0871ca19.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~6ff784789ede68d2.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~421455e3fbdc03f2.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~9d19ec6540cb4119.jxl 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~9d19ec6540cb4119.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~ebf86162d0853548.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~e90cfc42b3a16ed3.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~17458aeff43c8863.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~7ba6fe289c128877.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~1c3a6e72654731e5.avif 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~1c3a6e72654731e5.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~510566a586f00cc5.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~0550eaa5bf359d1c.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~30f0af8d4f116c19.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~b6ea85af59617eeb.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~fab27bf25c0546c9.webp 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~fab27bf25c0546c9.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/_thumb~9d19ec6540cb4119.jxl" loading="lazy" width="3842" height="2162" data-kind="media" data-input-path="/content/articles/crates-io-phishing-attempt/_thumb.jxl" alt="Thumbnail for crates.io phishing attempt"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/crates-io-phishing-attempt" rel="noopener">
crates.io phishing attempt
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Sep 12, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
1 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/security">#security</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/crates-io-phishing-attempt" rel="noopener">
<div class="post-summary markup-container "><p data-bo="160">Earlier this week, an <a href="/articles/color-npm-package-compromised">npm supply chain attack</a>.</p>
<p data-bo="251">It’s turn for <a href="https://crates.io">crates.io</a>, the main public repository for <a href="https://rust-lang.org">Rust</a>
crates (packages).</p>
<p data-bo="378">The phishing e-mail looks like this:</p>
<figure
class="paragraph-like"
data-bo="416"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/phishing-email~13b1cc912a064403.w400.jxl 1x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/phishing-email~052f360399d29116.jxl 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/phishing-email~052f360399d29116.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/phishing-email~0965dc15bd5795cf.w400.avif 1x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/phishing-email~4adc3538b38cd5d0.avif 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/phishing-email~4adc3538b38cd5d0.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/phishing-email~569c8ebc7740ee8f.w400.webp 1x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/phishing-email~f5f81e8409287a73.webp 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/phishing-email~f5f81e8409287a73.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/phishing-email~052f360399d29116.jxl" loading="lazy" width="708" height="653" data-kind="media" data-input-path="/content/articles/crates-io-phishing-attempt/phishing-email.jxl" title="" alt="A phishing e-mail: Important: Breach notification regarding crates.io Hi, BurntSushi! We recently discovered that an unauthorized actor had compromised the crates.io infrastructure and accessed a limited amount of user information. The attacker's access was revoked, and we are currently reviewing our security posture. We are currently drafting a blog post to outline the timeline and the steps we took to mitigate this. In the meantime, we strongly suggest you to rotate your login info by signing in here to our internal SSO, which is a temporary fix to ensure that the attacker cannot modify any packages published by you. "></picture><figcaption><cite><a href="https://bsky.app/profile/burntsushi.net/post/3lynehptw6c2n
">Andrew Gallant on BlueSky
</a></cite></figcaption>
</figure><p data-bo="1262">And it leads to a GitHub login page that looks like this:</p>
<figure
class="paragraph-like"
data-bo="1321"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~f39542ca9ae9f0c3.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~5429425a2625794b.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~ff6053b5d2562aeb.w900.jxl 1x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~e78524d35ede5efb.jxl 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~e78524d35ede5efb.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~de116d2a77f034de.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~e4d40b2fbaa0c23e.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~5f55c6d615078899.w900.avif 1x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~f28292ec85f76009.avif 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~f28292ec85f76009.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~21a0077b4369fdc4.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~34797abd3fa323ca.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~324abfa3a52194e8.w900.webp 1x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~bf34180d4a8419bd.webp 1x,https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~bf34180d4a8419bd.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/crates-io-phishing-attempt/github-phish~e78524d35ede5efb.jxl" loading="lazy" width="1322" height="1378" data-kind="media" data-input-path="/content/articles/crates-io-phishing-attempt/github-phish.jxl" title="" alt="A fake GitHub sign-in page. "></picture><figcaption><cite><a href="https://github.com/rust-lang/crates.io/discussions/11889#discussion-8886064
">Barre on GitHub
</a></cite></figcaption>
</figure><p data-bo="1548">Several maintainers received it — the issue is being discussed <a href="https://github.com/rust-lang/crates.io/discussions/11889">on GitHub</a>.</p>
<p data-bo="1685">The <a href="https://www.rust-lang.org/governance/teams/dev-tools#team-crates-io">crates.io team</a> has acknowledged
the attack and said they’d see if they can do something about it.</p>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/crates-io-phishing-attempt" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~c384b8719a78e931.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~4be954b3ecd97e8c.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~9370b8996b0fe39e.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~013147481f197406.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~99b0ac4f20ac8d54.jxl 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~99b0ac4f20ac8d54.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~abacc73e0e3f01ae.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~8133e836a728b95a.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~b6eae386b0495658.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~7c0b8241d5616bff.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~32f611defff2a1be.avif 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~32f611defff2a1be.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~b402471be09db364.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~43a5932351237b2a.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~e686a9ccc05768ad.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~7bb6b3d54e93eeb4.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~3645459090a22658.webp 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~3645459090a22658.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/_thumb~99b0ac4f20ac8d54.jxl" loading="lazy" width="3842" height="2162" data-kind="media" data-input-path="/content/articles/color-npm-package-compromised/_thumb.jxl" alt="Thumbnail for color npm package compromised"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/color-npm-package-compromised" rel="noopener">
color npm package compromised
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Sep 08, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
4 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/npm">#npm</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/color-npm-package-compromised" rel="noopener">
<div class="post-summary markup-container "><p data-bo="148">On September 8 2025, around 13:00 UTC, someone compromised <a href="https://www.npmjs.com/~qix">Josh Junon’s npm
account (qix)</a> and started publishing backdoored
versions of his package.</p>
<p data-bo="328">Someone noticed and let Josh know:</p>
<figure
class="paragraph-like"
data-bo="364"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~0ad954d4042cc44e.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~a5ec0b93bba7ec30.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~f4efba9875cd59ab.w900.jxl 1x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~4a9e74f87760a4af.jxl 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~4a9e74f87760a4af.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~a77a052fa30939ec.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~2c4593ff2e898847.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~424c77cae67f76e3.w900.avif 1x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~2a91320fae70db76.avif 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~2a91320fae70db76.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~4b4a2f263f473471.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~4b2488064d4e9adb.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~ca45cce753873308.w900.webp 1x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~33efd9d23f34908e.webp 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~33efd9d23f34908e.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/charlie-noticed@2x~4a9e74f87760a4af.jxl" loading="lazy" width="595" height="177" data-kind="media" data-input-path="/content/articles/color-npm-package-compromised/charlie-noticed@2x.jxl" title="" alt="Hey. Your npm account seems to have been compromised. 1 hour ago it started posting packages with backdoors to all your popular packages. "></picture><figcaption><cite><a href="https://bsky.app/profile/charlieeriksen.bsky.social/post/3lydffcyulc2n
">Charlie Eriksen on BlueSky
</a></cite></figcaption>
</figure><p data-bo="713">Josh confirmed he’d gotten pwned by a fake 2FA (two-factor authentication) reset e-mail:</p>
<figure
class="paragraph-like"
data-bo="803"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~a179783538de1f4d.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~7c915c01a7921e87.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~1a4695014120bb13.w900.jxl 1x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~ca37f72d582a4442.jxl 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~ca37f72d582a4442.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~a8368bb997745224.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~731a6e9261ec5aa6.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~2ef1999737857730.w900.avif 1x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~0625d89fd48a2fad.avif 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~0625d89fd48a2fad.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~97b58ff0b566eb23.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~ab64f921056092b7.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~6f99f1fb2081d88c.w900.webp 1x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~ff16c7198a608a53.webp 1x,https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~ff16c7198a608a53.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/color-npm-package-compromised/josh-fake-2fa@2x~ca37f72d582a4442.jxl" loading="lazy" width="592" height="396" data-kind="media" data-input-path="/content/articles/color-npm-package-compromised/josh-fake-2fa@2x.jxl" title="" alt="Yep, I've been pwned. 2FA reset email, looked very legitimate. Only NPM affected. I've sent an email off to @npmjs.bsky.social to see if I can get access again. Sorry everyone, I should have paid more attention. Not like me; have had a stressful week. Will work to get this cleaned up. "></picture><figcaption><cite><a href="https://bsky.app/profile/bad-at-computer.bsky.social/post/3lydioq5swk2y
">Josh Junon on BlueSky
</a></cite></figcaption>
</figure><p data-bo="1329">The phishing e-mail came from <code>npmsj.help</code> (registered 3 days prior) and claimed
users had to reset their 2FA:</p>
<a id="the-payload" href="#the-payload" class="anchor"></a>
<a id="current-situation" href="#current-situation" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/color-npm-package-compromised" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~907e4d38158bdbea.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~f2b2f25487e46d78.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~8b7d1e94a95e62a3.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~4a43843df23954bd.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~1296470a3eda8e02.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~1296470a3eda8e02.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~992cb1bfa2fa3425.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~2ef65686eeb15274.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~2b187fdee50d2d62.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~33b5ac64ed8ea933.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~017315af1be83956.avif 1x,https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~017315af1be83956.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~5dbd1a946039a2a3.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~689bd5f35aaa1655.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~ec947757fb442992.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~fce8d490ef4fbff2.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~dc1634dac63fc99e.webp 1x,https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~dc1634dac63fc99e.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/_thumb~1296470a3eda8e02.jxl" loading="lazy" width="3842" height="2162" data-kind="media" data-input-path="/content/articles/the-science-of-loudness/_thumb.jxl" alt="Thumbnail for The science of loudness"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/the-science-of-loudness" rel="noopener">
The science of loudness
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Aug 22, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
13 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/audio">#audio</a></span>
<span>·</span>
<span><a href="/tags/maths">#maths</a></span>
<span>·</span>
<span><a href="/tags/physics">#physics</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/the-science-of-loudness" rel="noopener">
<div class="post-summary markup-container "><p data-bo="246">My watch has a “Noise” app: it shows <math display="inline"><mrow><mi mathvariant="normal">d</mi><mi mathvariant="normal">B</mi></mrow></math>, for decibels.</p>
<p data-bo="313"><video controls playsinline preload="none" loading="lazy" width="3840" height="2160" data-kind="media" data-input-path="/content/articles/the-science-of-loudness/apple-watch-decibel-meter.mp4" poster="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/apple-watch-decibel-meter.thumb" class="" title="" alt="A video of my Apple Watch showing me how loud the sound coming from my speakers is.
"><source src="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/apple-watch-decibel-meter~d96a722c49fdda5d.mp4" type="video/mp4; codecs=av01.0.08M.08,opus"><source src="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/apple-watch-decibel-meter~e53858e76f36614d.h264+aac.mp4" type="video/mp4; codecs=avc1.640034,mp4a.40.2"><source src="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/apple-watch-decibel-meter~fb169411c4d8653e.vp9+opus.webm" type="video/webm; codecs=vp09.00.41.08,opus">Your browser does not support the video tag.</video></p><p data-bo="464">My amp has a volume knob, which also shows decibels, although.. negative ones, this time.</p>
<p data-bo="555"><video controls playsinline preload="none" loading="lazy" width="3840" height="2160" data-kind="media" data-input-path="/content/articles/the-science-of-loudness/adjust-volume.mp4" poster="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/adjust-volume.thumb" class="" title="" alt="A video of me adjusting my volume on my Cambridge AXR100 amplifier. The
volume goes from -61 to -32 decibels in that video.
"><source src="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/adjust-volume~46153fb1ad60f230.mp4" type="video/mp4; codecs=av01.0.08M.08,opus"><source src="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/adjust-volume~a8af11cbe6d90598.h264+aac.mp4" type="video/mp4; codecs=avc1.640034,mp4a.40.2"><source src="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/adjust-volume~9a7388f3f768f948.vp9+opus.webm" type="video/webm; codecs=vp09.00.41.08,opus">Your browser does not support the video tag.</video></p><p data-bo="746">And finally, my video editing software has a ton of meters — which are all in decibel or
decibel-adjacent units.</p>
<p data-bo="862"><video controls playsinline preload="none" loading="lazy" width="2002" height="1127" data-kind="media" data-input-path="/content/articles/the-science-of-loudness/tons-of-meters@2x.mp4" poster="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/tons-of-meters@2x.thumb" class="" title="" alt="A screenshot of DaVinci Resolve, showing various meters: we have Bus 1,
Control Room with TP, Loudness, YouTube (LUFS), then Loudness History
with Integrated, Momentary and Short Term. In the Mixer, each track has
its meter.
"><source src="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/tons-of-meters@2x~9cc29f2809d1202a.mp4" type="video/mp4; codecs=av01.0.08M.08,opus"><source src="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/tons-of-meters@2x~da316f2ab0e0aeb5.h264+aac.mp4" type="video/mp4; codecs=avc1.640034,mp4a.40.2"><source src="https://cdn.fasterthanli.me/content/articles/the-science-of-loudness/tons-of-meters@2x~e50f9e76cf48090c.vp9+opus.webm" type="video/webm; codecs=vp09.00.41.08,opus">Your browser does not support the video tag.</video></p>
<a id="what-even-is-sound" href="#what-even-is-sound" class="anchor"></a>
<a id="under-pressure" href="#under-pressure" class="anchor"></a>
<a id="signal-processing" href="#signal-processing" class="anchor"></a>
<a id="root-mean-square" href="#root-mean-square" class="anchor"></a>
<a id="sample-peak-true-peak" href="#sample-peak-true-peak" class="anchor"></a>
<a id="the-loudness-wars" href="#the-loudness-wars" class="anchor"></a>
<a id="a-weighting" href="#a-weighting" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/the-science-of-loudness" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/summer-fasterthanlime-update" rel="noopener">
Summer fasterthanlime update
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Aug 15, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
8 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/meta">#meta</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/summer-fasterthanlime-update" rel="noopener">
<div class="post-summary markup-container "><p data-bo="147">There are news!</p>
<div data-bo="166" class="tip markup-container">
<div class="tip-header bear-mark">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~f8031274cabccdf6.w400.jxl 1x,https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~451aa11f175f8fc4.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~2add1c1dfe1cf845.w900.jxl 1x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~85823bd96ffd0bb6.jxl 1x,https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~85823bd96ffd0bb6.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~e1d6acd7da0c8bd7.w400.avif 1x,https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~fe0a016a137f310a.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~909ed9e4ba5c3317.w900.avif 1x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~165a8452ce0788cd.avif 1x,https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~165a8452ce0788cd.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~c7e5fe0bec9ef4d6.w400.webp 1x,https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~430cbb8ae0eaa295.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~9df5546a60e748fc.w900.webp 1x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~ff0c651f16d7613d.webp 1x,https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~ff0c651f16d7613d.webp 2x"><img src="https://cdn.fasterthanli.me/content/img/reimena/coolbear-idea~85823bd96ffd0bb6.jxl" loading="lazy" width="48" height="48" data-kind="media" data-input-path="/content/img/reimena/coolbear-idea.jxl" class="bear" alt="Cool bear"></picture>
Cool Bear's hot tip
</div>
<p data-bo="177">TL;DR: If you’re a patron or sponsor, check your <a href="/profile">Profile</a> page to
get detailed explainers of every perk. You’ll need to log in. Duh.</p>
</div><p data-bo="322">Here are all the changes I’m implementing, summarized as a table:</p>
<div class="responsive-table" data-bo="389"><table><thead><td>Before</td><td>After</td></thead><tr><td>📚 Articles remain exclusive for <strong>6 months</strong></td><td>Early access (<strong>couple weeks</strong>) for Silver tier</td></tr><tr><td>🎞️ No early access for video</td></tr></table></div>
<a id="looking-back" href="#looking-back" class="anchor"></a>
<a id="a-discord-server" href="#a-discord-server" class="anchor"></a>
<a id="early-access-revamp" href="#early-access-revamp" class="anchor"></a>
<a id="dual-rss-feeds" href="#dual-rss-feeds" class="anchor"></a>
<a id="bye-ko-fi" href="#bye-ko-fi" class="anchor"></a>
<a id="more-casual-posting" href="#more-casual-posting" class="anchor"></a>
<a id="what-about-content-that-was-still-exclusive" href="#what-about-content-that-was-still-exclusive" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/summer-fasterthanlime-update" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
data-youtube="OzCbdsVVnKI"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~ddf90f6aeab4bee1.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~c57a37a8e12a1e11.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~cefb4d1d3e243365.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~c02dcb7790383407.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~a202435ad1ce5467.jxl 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~a202435ad1ce5467.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~e6e551fff6334629.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~f6407cbf84441716.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~5e351777c3e9e8d4.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~71d0b72a26ca06cf.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~333bb6ed82eae756.avif 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~333bb6ed82eae756.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~e188367af47b4df6.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~77c24b01319b7fd6.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~2ca9e5782acc441b.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~ad97052cbba4c39e.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~99bfd1fcc5cc708c.webp 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~99bfd1fcc5cc708c.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/_thumb~a202435ad1ce5467.jxl" loading="lazy" width="3842" height="2162" data-kind="media" data-input-path="/content/articles/all-color-is-best-effort/_thumb.jxl" alt="Thumbnail for All color is best-effort"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/all-color-is-best-effort" rel="noopener">
All color is best-effort
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Jun 27, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
23 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/color">#color</a></span>
<span>·</span>
<span><a href="/tags/video">#video</a></span>
<span>·</span>
<span><a href="/tags/dsp">#dsp</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/all-color-is-best-effort" rel="noopener">
<div class="post-summary markup-container "><p data-bo="224">I do not come to you with answers today, but rather some observations and a lot of questions.</p>
<a id="the-weird-glitch" href="#the-weird-glitch" class="anchor"><h2>The weird glitch</h2></a>
<p data-bo="340">Recently I was editing some video and I noticed this:</p>
<p data-bo="395">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~bc15541e1738a8c6.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~611f0686a4304520.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~6c16884b3cbe3da0.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~9665a9740fd741f6.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~3c031f1f42693336.jxl 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~3c031f1f42693336.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~787a8860926cf053.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~bb7c6eecccd060d7.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~a7e8c949bca8b7a5.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~855d2918693652f1.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~9b7179dcf280ef82.avif 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~9b7179dcf280ef82.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~3eeef026e1c97bfb.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~2bd7304336f5d982.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~56622c6c2c1cd39a.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~80cae7813b764663.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~ecaf6f4a32a1a287.webp 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~ecaf6f4a32a1a287.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/dvr-circles@2x~3c031f1f42693336.jxl" loading="lazy" width="1966" height="1126" data-kind="media" data-input-path="/content/articles/all-color-is-best-effort/dvr-circles@2x.jxl" title="A screenshot of the video, there are visible circles at various places in the image. Some of them are black, some of them are white. The image itself shows some blue and white text composited on some blurry background, which doesn’t really matter for this, and there’s a red line horizontal up in the image. It’s very confusing." alt="A screenshot of the video, there are visible circles at various places in the image. Some of them are black, some of them are white. The image itself shows some blue and white text composited on some blurry background, which doesn’t really matter for this, and there’s a red line horizontal up in the image. It’s very confusing."></picture></p>
<p data-bo="748">Not what the finger is pointing at — the dots.</p>
<p data-bo="798">Here are the separate layers this image is made up of: the background is a stock image
I’ve licensed from Envato Elements:</p>
<p data-bo="922"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~82e4590a81a91669.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~396cd6f7cdde1715.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~01c4c3e679fc97cb.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~64b3776886a40bc2.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~dcfb5771209ddbd5.jxl 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~dcfb5771209ddbd5.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~64e6c779ed984060.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~948fae22ff317166.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~43dd5455b145f94a.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~13f8922bbb8fc4ec.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~8b931c6a0152f29e.avif 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~8b931c6a0152f29e.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~43323deba1e5ee6f.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~62b8e8b4e862037b.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~0ec387af3f70ae28.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~5cf8c742dcce6076.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~39bff319d2958a1f.webp 1x,https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~39bff319d2958a1f.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/all-color-is-best-effort/canyon-background@2x~dcfb5771209ddbd5.jxl" loading="lazy" width="1966" height="1126" data-kind="media" data-input-path="/content/articles/all-color-is-best-effort/canyon-background@2x.jxl" title="A picture of a canyon, darker than you’d expect." alt="A picture of a canyon, darker than you’d expect."></picture></p>
<p data-bo="1001">Because I use it as a background image, I’ve cranked down the exposition in the Color tab:</p>
<a id="playing-with-color-spaces" href="#playing-with-color-spaces" class="anchor"></a>
<a id="cie-chromaticity-diagram" href="#cie-chromaticity-diagram" class="anchor"></a>
<a id="our-first-transfer-function" href="#our-first-transfer-function" class="anchor"></a>
<a id="parade-scope" href="#parade-scope" class="anchor"></a>
<a id="more-transfer-functions" href="#more-transfer-functions" class="anchor"></a>
<a id="how-white-is-your-white" href="#how-white-is-your-white" class="anchor"></a>
<a id="conclusion" href="#conclusion" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/all-color-is-best-effort" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
data-youtube="0mqFCqw_XvI"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~1992d85196b18e08.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~e40b7f0566105ebf.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~cb6e049114ad3a57.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~8d381685e10bbd44.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~543e05c559d7666f.jxl 1x,https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~543e05c559d7666f.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~d4a5536e08b767fa.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~fc777106337e215d.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~9656a3798443bdce.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~78851fda6973500d.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~fe4fda46e22a1dc9.avif 1x,https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~fe4fda46e22a1dc9.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~5b9318fc7a437c93.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~510f37c51515c3c5.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~4376f607bf76f462.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~39d9b9f8cc2f1add.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~a5994634e3ccf952.webp 1x,https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~a5994634e3ccf952.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/introducing-facet-reflection-for-rust/_thumb~543e05c559d7666f.jxl" loading="lazy" width="2560" height="1440" data-kind="media" data-input-path="/content/articles/introducing-facet-reflection-for-rust/_thumb.jxl" alt="Thumbnail for Introducing facet: Reflection for Rust"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/introducing-facet-reflection-for-rust" rel="noopener">
Introducing facet: Reflection for Rust
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Jun 05, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
20 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/reflection">#reflection</a></span>
<span>·</span>
<span><a href="/tags/facet">#facet</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/introducing-facet-reflection-for-rust" rel="noopener">
<div class="post-summary markup-container "><p data-bo="946">I have long been at war against Rust compile times.</p>
<p data-bo="999">Part of the solution for me was to buy my way into Apple Silicon dreamland,
where builds are, like… faster. I remember every time I SSH into an x86_64
server, even the nice 64-core ones.</p>
<p data-bo="1189">And another part was, of course, to get dirty with Rust itself.</p>
<p data-bo="1254">I wrote <a href="/articles/why-is-my-rust-build-so-slow">Why is my Rust build so slow?</a>,
which goes in-depth into rust build performance, down to rustc self-profiling even!</p>
<a id="let-they-who-are-without-syn" href="#let-they-who-are-without-syn" class="anchor"></a>
<a id="monomorphization" href="#monomorphization" class="anchor"></a>
<a id="a-different-strategy" href="#a-different-strategy" class="anchor"></a>
<a id="today-tomorrow" href="#today-tomorrow" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/introducing-facet-reflection-for-rust" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
data-youtube="YtbUzIQw-so"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~2c60f64a5f7a6046.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~cc3bbe4af460c596.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~738df3d91c1b7066.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~3236ac1f651bda72.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~c169c35c5c82453e.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~c169c35c5c82453e.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~e2e8adbcdd5f12a9.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~9320faa0429802a4.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~db6912b113302feb.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~1064d44a9714e216.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~54d60847b1224017.avif 1x,https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~54d60847b1224017.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~3474c6ea6d75d18d.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~8364900b6c7baa1b.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~ea123563058502fd.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~03e84e7b9215e962.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~976ee1a8fa9d5aa6.webp 1x,https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~976ee1a8fa9d5aa6.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/the-virtue-of-unsynn/_thumb~c169c35c5c82453e.jxl" loading="lazy" width="3842" height="2162" data-kind="media" data-input-path="/content/articles/the-virtue-of-unsynn/_thumb.jxl" alt="Thumbnail for The virtue of unsynn"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/the-virtue-of-unsynn" rel="noopener">
The virtue of unsynn
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">May 29, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
21 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/the-virtue-of-unsynn" rel="noopener">
<div class="post-summary markup-container "><a id="addressing-the-rumors" href="#addressing-the-rumors" class="anchor"><h2>Addressing the rumors</h2></a>
<p data-bo="229">There have been rumors going around, in the Reddit thread for
<a href="https://github.com/facet-rs/facet">facet</a>, my take on reflection in Rust, which
happened a bit too early, but here we are, cat’s out of the bag, let’s talk
about it!</p>
<p data-bo="459">Rumors that I, podcaster/youtuber fasterthanlime, want to kill
<a href="https://lib.rs/crates/serde">serde</a>, serialization / deserialization
framework loved by many and which contributed greatly to Rust’s success, and I
just wanted to address those rumors and say that…</p>
<a id="comparing-apples-and-nuclear-submarines" href="#comparing-apples-and-nuclear-submarines" class="anchor"></a>
<a id="macro-expansion" href="#macro-expansion" class="anchor"></a>
<a id="build-times-again" href="#build-times-again" class="anchor"></a>
<a id="enter-unsynn" href="#enter-unsynn" class="anchor"></a>
<a id="warm-builds" href="#warm-builds" class="anchor"></a>
<a id="putting-things-in-perspective" href="#putting-things-in-perspective" class="anchor"></a>
<a id="tooling" href="#tooling" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/the-virtue-of-unsynn" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~48175c800b15882f.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~4973353e0d0082ec.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~d99aa912c3cde60c.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~abbded8f5300df71.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~0c8a351e521e4121.jxl 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~0c8a351e521e4121.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~ad2e385836cb397c.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~29f2c71325e1ef7c.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~c8e7e3ce0f6870b0.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~88f48b04a8cdcc39.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~4fe88f27ae5f27d0.avif 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~4fe88f27ae5f27d0.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~ac533b7e852cebe9.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~32d37325b3988730.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~40e65aca1be64578.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~0689f96e10c46abc.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~99bc2fd5f607c5a8.webp 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~99bc2fd5f607c5a8.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/_thumb~0c8a351e521e4121.jxl" loading="lazy" width="3014" height="1808" data-kind="media" data-input-path="/content/articles/open-sourcing-the-home-cms/_thumb.jxl" alt="Thumbnail for Open sourcing the home CMS"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/open-sourcing-the-home-cms" rel="noopener">
Open sourcing the home CMS
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Apr 22, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
7 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/oss">#oss</a></span>
<span>·</span>
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/ftl-infra">#ftl-infra</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/open-sourcing-the-home-cms" rel="noopener">
<div class="post-summary markup-container "><p data-bo="140">I’ve been bragging about my website software for years! For… whew, it’s been 5 years!</p>
<figure
class="paragraph-like"
data-bo="229"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~dadde2bc6ed46bf5.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~ab5c6b2bc29c9c6a.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~c3237faef055e8cf.w900.jxl 1x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~57268eaf77aa3bf7.jxl 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~57268eaf77aa3bf7.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~915be8263dc3d03a.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~6a9ff5bff6b59f1e.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~35d8aeeaeda09852.w900.avif 1x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~7f0f4780f7ca8970.avif 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~7f0f4780f7ca8970.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~e8487760338c207e.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~f891dcabcc93ee1e.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~9bf9ba8dd701061f.w900.webp 1x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~d969fd1992b4a4b2.webp 1x,https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~d969fd1992b4a4b2.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/open-sourcing-the-home-cms/early-git-history@2x~57268eaf77aa3bf7.jxl" loading="lazy" width="643" height="527" data-kind="media" data-input-path="/content/articles/open-sourcing-the-home-cms/early-git-history@2x.jxl" title="I didn't want to make a CMS! I did it out of spite! " alt="A screenshot of github commits for the beginning of my website. It has commit messages like 'learning rusqlite', 'walk stuff', 'import input files', 'parse frontmatter and stuff', and 'do stuff in parallel'. "></picture><figcaption><div class="markup-container figure-caption"><p>I didn't want to make a CMS! I did it out of spite!</p>
</div></figcaption>
</figure><p data-bo="581">I’ve been teasing folks about the cool things I did from the beginning — here are
all the articles and series I’ve written that mention it:</p>
<ul><li><a href="/articles/a-new-website-for-2020">2020: A new website</a></li>
<li><a href="/series/dont-shell-out">2021: Don’t shell out!</a></li>
<li><a href="/series/updating-fasterthanli-me-for-2022">2022: Updating fasterthanli.me</a></li>
</ul>
<a id="open-sourced-components" href="#open-sourced-components" class="anchor"></a>
<a id="bearcove-home-tree-sitter" href="#bearcove-home-tree-sitter" class="anchor"></a>
<a id="bearcove-home-drawio" href="#bearcove-home-drawio" class="anchor"></a>
<a id="bearcove-homebrew-tap" href="#bearcove-homebrew-tap" class="anchor"></a>
<a id="bearcove-timelord" href="#bearcove-timelord" class="anchor"></a>
<a id="bearcove-beardist" href="#bearcove-beardist" class="anchor"></a>
<a id="bearcove-home" href="#bearcove-home" class="anchor"></a>
<a id="closing-words" href="#closing-words" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/open-sourcing-the-home-cms" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
data-youtube="zo6yZisg7N0"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~20b0994f70a551d2.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~1bea5d5559a5b57a.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~5d5885ee21bfed0f.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~38aa1573500d11bd.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~f89402ada7119728.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~f89402ada7119728.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~a8f963f80f76ff3e.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~e53a8fe5e15af75c.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~00d2d205a7c03a98.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~2bd4c0b5ba52b8f5.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~c6bfd6cd7d528553.avif 1x,https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~c6bfd6cd7d528553.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~473dfeb062d5afab.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~c26737cb6a0984ff.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~89f6238e4c3d2a5d.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~86085d630758a32d.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~d54acbe3a98e2ff7.webp 1x,https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~d54acbe3a98e2ff7.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/the-promise-of-rust/_thumb~f89402ada7119728.jxl" loading="lazy" width="3842" height="2162" data-kind="media" data-input-path="/content/articles/the-promise-of-rust/_thumb.jxl" alt="Thumbnail for The promise of Rust"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/the-promise-of-rust" rel="noopener">
The promise of Rust
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Apr 16, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
29 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/memory-safety">#memory-safety</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/the-promise-of-rust" rel="noopener">
<div class="post-summary markup-container "><p data-bo="200">The part that makes Rust scary is the part that makes it unique.</p>
<p data-bo="266">And it’s also what I miss in other programming languages — let me explain!</p>
<p data-bo="344">Rust syntax starts simple.</p>
<p data-bo="372">This function prints a number:</p>
<figure role="region" aria-label="Rust code block" class="code-block has-language-tag" translate="no" data-lang="rust" data-bo="404"><span class="language-tag" title="Rust"></span><code class="scroll-wrapper"><a-k>fn</a-k> <a-f>show</a-f><a-p>(</a-p><a-v>n</a-v><a-p>:</a-p> <a-t>i64</a-t><a-p>)</a-p> <a-p>{</a-p>
<a-m>println!</a-m><a-p>(</a-p><a-s>"n = {n}"</a-s><a-p>);</a-p>
<a-p>}</a-p>
</code></figure><p data-bo="462">And this program calls that function — it looks like any C-family language so far,
we got parentheses, we got curly brackets, we got, uhh…</p>
<a id="rust-move-semantics" href="#rust-move-semantics" class="anchor"></a>
<a id="javascript-semantics" href="#javascript-semantics" class="anchor"></a>
<a id="go-semantics" href="#go-semantics" class="anchor"></a>
<!-- playwall -->
<a id="deep-cloning" href="#deep-cloning" class="anchor"></a>
<a id="constness-in-c-and-c" href="#constness-in-c-and-c" class="anchor"></a>
<a id="linear-types" href="#linear-types" class="anchor"></a>
<a id="immutability-in-rust" href="#immutability-in-rust" class="anchor"></a>
<a id="unsafe-rust" href="#unsafe-rust" class="anchor"></a>
<a id="aliasing-xor-mutability" href="#aliasing-xor-mutability" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/the-promise-of-rust" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~f6210964cebeb5b8.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~d20f1d3e32c36005.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~3ef6bcc971efd6d3.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~56c3c0bd43df8b5d.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~ce3deeea84bf1a9b.jxl 1x,https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~ce3deeea84bf1a9b.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~5b03336822e17435.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~0cb44e43f1c173ef.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~0ea1271ed8a5f441.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~fa69a4a1927a3444.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~84b9f9243dc3fe8b.avif 1x,https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~84b9f9243dc3fe8b.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~b259879f090fc355.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~a9c1c9bee58c0cd7.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~90270132284f4d67.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~098cf7e02d091a9f.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~3efac684937bdeb5.webp 1x,https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~3efac684937bdeb5.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/that-health-is-mental/_thumb~ce3deeea84bf1a9b.jxl" loading="lazy" width="1920" height="1080" data-kind="media" data-input-path="/content/articles/that-health-is-mental/_thumb.jxl" alt="Thumbnail for That health is mental"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/that-health-is-mental" rel="noopener">
That health is mental
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Apr 09, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
11 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/mental-health">#mental-health</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/that-health-is-mental" rel="noopener">
<div class="post-summary markup-container "><div data-bo="108" class="disclosure paragraph-like">
<p data-bo="55"><strong>Disclaimer</strong>:</p>
<p data-bo="126">Trigger warning: depression, talk of suicide.</p>
</div><p data-bo="173">It’s been a while since I wrote a mental health piece — but I think it’s
important to occasionally stop, take a breather, and think about how we feel.</p>
<p data-bo="327">So.</p>
<p data-bo="332"><em>deep breath</em></p>
<p data-bo="347">I’m okay, I think? Just a little restless.</p>
<a id="a-bit-of-personal-context" href="#a-bit-of-personal-context" class="anchor"><h2>A bit of personal context</h2></a>
<p data-bo="421">For those keeping score, I went through major life events in 2023 — a divorce, a move,
and the news that I might need a second round of jaw surgery.</p>
<a id="meds-meds-meds" href="#meds-meds-meds" class="anchor"></a>
<a id="autism-adhd-audhd" href="#autism-adhd-audhd" class="anchor"></a>
<a id="what-now" href="#what-now" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/that-health-is-mental" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~1e1efec60922e341.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~1aecb42ed6080e2a.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~e5fecf49981800ee.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~0ceea5718bc6b0dc.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~efb145c6a7972da4.jxl 1x,https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~efb145c6a7972da4.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~96f0e39fe2ed3d97.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~472f964cca8530cf.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~1f0ca9b2cfc16f71.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~f3bf2f80ce9955ce.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~dbc2cc0e9a180f39.avif 1x,https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~dbc2cc0e9a180f39.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~f2da90a8f3c63f9b.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~3a7c8fb3db2e3319.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~87bd0cf777c7b87e.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~658fbded8401763d.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~a8f1ed6e9a057307.webp 1x,https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~a8f1ed6e9a057307.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/more-devops-than-i-bargained-for/_thumb~efb145c6a7972da4.jxl" loading="lazy" width="1920" height="1080" data-kind="media" data-input-path="/content/articles/more-devops-than-i-bargained-for/_thumb.jxl" alt="Thumbnail for More devops than I bargained for"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/more-devops-than-i-bargained-for" rel="noopener">
More devops than I bargained for
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Apr 07, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
21 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/kubernetes">#kubernetes</a></span>
<span>·</span>
<span><a href="/tags/calico">#calico</a></span>
<span>·</span>
<span><a href="/tags/ipv6">#ipv6</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/more-devops-than-i-bargained-for" rel="noopener">
<div class="post-summary markup-container "><a id="background" href="#background" class="anchor"><h2>Background</h2></a>
<p data-bo="149">I recently had a bit of <a href="/articles/impromptu-disaster-recovery">impromptu disaster recovery</a>,
and it gave me a hunger for more! More downtime! More kubernetes manifest!
More DNS! Ahhhh!</p>
<p data-bo="336">The plan was really simple. I love dedicated Hetzner servers with all my heart but they are not very fungible.</p>
<p data-bo="448">You have to wait entire minutes for a new dedicated server to be provisioned.
Sometimes you pay a setup fee, et cetera. And at some point to server static
websites and serve as a K3S server, it’s simply just too big, and approximately
twice the price that I should pay.</p>
<a id="has-anyone-ever-built-it-for-arm64-linux-before" href="#has-anyone-ever-built-it-for-arm64-linux-before" class="anchor"></a>
<a id="multi-arch-container-images" href="#multi-arch-container-images" class="anchor"></a>
<a id="base-images-regctl" href="#base-images-regctl" class="anchor"></a>
<a id="more-like-ipv5" href="#more-like-ipv5" class="anchor"></a>
<a id="the-nat-king-calls" href="#the-nat-king-calls" class="anchor"></a>
<a id="why-the-fuck-is-everything-broken" href="#why-the-fuck-is-everything-broken" class="anchor"></a>
<a id="bye-natalie" href="#bye-natalie" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/more-devops-than-i-bargained-for" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~31dddd7e724e09d3.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~27e75bac05d8ec4b.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~94336b6f1b98579c.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~17eb78348a2ba25d.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~f5c87c707a158615.jxl 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~f5c87c707a158615.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~3f1301e72677267f.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~25bb6984fe468e14.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~d0781c3f61c7e817.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~fd78b72dd6453632.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~eb0ca444d63e88d1.avif 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~eb0ca444d63e88d1.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~1cb413e98b287eab.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~5d5bdfe51dc84007.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~1555d5c1aef555f2.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~af3492e1da8d632a.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~6a963bc3f01f6b3d.webp 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~6a963bc3f01f6b3d.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/_thumb~f5c87c707a158615.jxl" loading="lazy" width="1921" height="1080" data-kind="media" data-input-path="/content/articles/impromptu-disaster-recovery/_thumb.jxl" alt="Thumbnail for Impromptu disaster recovery"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/impromptu-disaster-recovery" rel="noopener">
Impromptu disaster recovery
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Mar 28, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
40 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/kubernetes">#kubernetes</a></span>
<span>·</span>
<span><a href="/tags/devops">#devops</a></span>
<span>·</span>
<span><a href="/tags/llm">#llm</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/impromptu-disaster-recovery" rel="noopener">
<div class="post-summary markup-container "><a id="background" href="#background" class="anchor"><h2>Background</h2></a>
<blockquote><p data-bo="145">im-promp-tu (<code>im-ˈpräm(p)-(ˌ)tü</code>)</p>
<ol start="1"><li><p data-bo="190">made, done, or formed on or as if on the spur of the moment: <a href="https://www.merriam-webster.com/dictionary/improvised">improvised</a></p>
</li>
<li><p data-bo="326">composed or uttered without previous preparation: <a href="https://www.merriam-webster.com/dictionary/extemporaneous">extemporaneous</a></p>
</li>
</ol>
<p data-bo="456"><a href="https://www.merriam-webster.com/dictionary/impromptu">Merriam-Webster</a></p>
</blockquote>
<p data-bo="529">On March 18th, 2025, I thought I would look into self-hosted project management
solutions — something kanban-y, but.. better?</p>
<figure
class="paragraph-like"
data-bo="658"><picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~9ad11f43cb6d0e44.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~100ea6c822aa7dec.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~ff8c2d0c0067f846.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~7bd1d6fe30b467e7.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~b4bc2b8bc06d1645.jxl 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~b4bc2b8bc06d1645.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~ea2de89efdf9d35e.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~237380f7c9c2d1d0.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~3845793759a93024.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~7136e281b03f3ffa.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~745613f6aaadf300.avif 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~745613f6aaadf300.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~ad8467cd28541565.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~9aec87da7a230bbb.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~c509af87e260fb83.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~449c9db68cc15783.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~24e9b79bc76baa2c.webp 1x,https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~24e9b79bc76baa2c.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/impromptu-disaster-recovery/wekan@2x~b4bc2b8bc06d1645.jxl" loading="lazy" width="1084" height="793" data-kind="media" data-input-path="/content/articles/impromptu-disaster-recovery/wekan@2x.jxl" title="This one does not spark joy. " alt="A screenshot of WeKan, the open-source Kanban. It looks.. from another age."></picture><figcaption><div class="markup-container figure-caption"><p>This one does not spark joy.</p>
</div></figcaption>
</figure>
<a id="how-i-deploy-stuff-on-k3s" href="#how-i-deploy-stuff-on-k3s" class="anchor"></a>
<a id="the-k3s-reconciler" href="#the-k3s-reconciler" class="anchor"></a>
<a id="the-reformattening" href="#the-reformattening" class="anchor"></a>
<a id="no-thoughts-head-weighty" href="#no-thoughts-head-weighty" class="anchor"></a>
<a id="gpt-4o" href="#gpt-4o" class="anchor"></a>
<a id="claude-3-7-sonnet" href="#claude-3-7-sonnet" class="anchor"></a>
<a id="deepseek-r1" href="#deepseek-r1" class="anchor"></a>
<a id="mistral-s-le-chat" href="#mistral-s-le-chat" class="anchor"></a>
<a id="the-aftermath" href="#the-aftermath" class="anchor"></a>
<a id="from-bad-to-worse" href="#from-bad-to-worse" class="anchor"></a>
<a id="no-matter-how-prepared" href="#no-matter-how-prepared" class="anchor"></a>
<a id="rsync-or-swim" href="#rsync-or-swim" class="anchor"></a>
<a id="debian-12-reinstall" href="#debian-12-reinstall" class="anchor"></a>
<a id="a-new-k3s-cluster" href="#a-new-k3s-cluster" class="anchor"></a>
<a id="just-enough-ansible-to-be-dangerous" href="#just-enough-ansible-to-be-dangerous" class="anchor"></a>
<a id="ca-troubles" href="#ca-troubles" class="anchor"></a>
<a id="bringing-back-the-essentials" href="#bringing-back-the-essentials" class="anchor"></a>
<a id="traefik-v3" href="#traefik-v3" class="anchor"></a>
<a id="cert-manager" href="#cert-manager" class="anchor"></a>
<a id="minio" href="#minio" class="anchor"></a>
<a id="k8up" href="#k8up" class="anchor"></a>
<a id="reflector" href="#reflector" class="anchor"></a>
<a id="cloudnativepg" href="#cloudnativepg" class="anchor"></a>
<a id="bringing-forgejo-back" href="#bringing-forgejo-back" class="anchor"></a>
<a id="postgres" href="#postgres" class="anchor"></a>
<a id="persistent-volume-restore" href="#persistent-volume-restore" class="anchor"></a>
<a id="deployment-service-ingress" href="#deployment-service-ingress" class="anchor"></a>
<a id="bringing-home-back" href="#bringing-home-back" class="anchor"></a>
<a id="zero-downtime-deploys" href="#zero-downtime-deploys" class="anchor"></a>
<a id="closing-words" href="#closing-words" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/impromptu-disaster-recovery" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
data-youtube="RYHYiXMJdZI"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~f2a239e72967748b.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~78624fba11f10410.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~1d79c95873c901a7.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~4aea1dcf33e9e71e.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~d1fb37a98b002c38.jxl 1x,https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~d1fb37a98b002c38.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~0650f0ec5d1a72e9.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~191fa5d5c41ea737.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~568f30d71f466b37.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~980d0d517451f3c8.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~9a5aadf8070bc56a.avif 1x,https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~9a5aadf8070bc56a.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~44535419e3831b9d.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~54eb5f575b152bc3.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~0e06866c44750937.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~712acbf7f530d0f7.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~03f2c246c00d29c9.webp 1x,https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~03f2c246c00d29c9.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/the-case-for-sans-io/_thumb~d1fb37a98b002c38.jxl" loading="lazy" width="1920" height="1080" data-kind="media" data-input-path="/content/articles/the-case-for-sans-io/_thumb.jxl" alt="Thumbnail for The case for sans-io"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/the-case-for-sans-io" rel="noopener">
The case for sans-io
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Feb 07, 2025</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
26 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/zip">#zip</a></span>
<span>·</span>
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/async">#async</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/the-case-for-sans-io" rel="noopener">
<div class="post-summary markup-container "><p data-bo="208">The most popular option to decompress ZIP files from the Rust programming
language is a crate simply named <a href="https://lib.rs/crates/zip" id="zip">zip</a> — At the time of this writing, it has 48
million downloads. It’s fully-featured, supporting various compression methods,
encryption, and even supports writing zip files.</p>
<p data-bo="528">However, that’s not the crate <em>everyone</em> uses to read ZIP files. Some
applications benefit from using asynchronous I/O, especially if they decompress
archives that they download from the network.</p>
<a id="character-encoding-differences" href="#character-encoding-differences" class="anchor"></a>
<a id="platform-differences" href="#platform-differences" class="anchor"></a>
<a id="the-end-of-central-directory-record" href="#the-end-of-central-directory-record" class="anchor"></a>
<a id="boundary-confusion" href="#boundary-confusion" class="anchor"></a>
<!-- playwall -->
<a id="not-doing-any-i-o-at-all" href="#not-doing-any-i-o-at-all" class="anchor"></a>
<a id="the-structure-of-rc-zip" href="#the-structure-of-rc-zip" class="anchor"></a>
<a id="bringing-io-uring-into-it" href="#bringing-io-uring-into-it" class="anchor"></a>
<a id="plugging-rc-zip-into-monoio" href="#plugging-rc-zip-into-monoio" class="anchor"></a>
<a id="closing-words" href="#closing-words" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/the-case-for-sans-io" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
data-youtube="bnmln9HtqEI"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~2d240ce0e1381121.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~c83819c43714d6ce.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~f4142cfeb0fe692c.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~5ce03ff7ce35a5db.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~213533343976dcc7.jxl 1x,https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~213533343976dcc7.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~d9a6bf9343235ec3.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~058c8c49bde251a7.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~d7719725a209f400.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~1728939ca4bda5d9.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~4a82eaead99d0c30.avif 1x,https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~4a82eaead99d0c30.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~daa889eb3ea209d1.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~4d2c8220e8f6ef75.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~2192fb89b47f49a8.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~aba81abc75f6f7c3.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~b8a957595ab00080.webp 1x,https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~b8a957595ab00080.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/catching-up-with-async-rust/_thumb~213533343976dcc7.jxl" loading="lazy" width="1920" height="1080" data-kind="media" data-input-path="/content/articles/catching-up-with-async-rust/_thumb.jxl" alt="Thumbnail for Catching up with async Rust"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/catching-up-with-async-rust" rel="noopener">
Catching up with async Rust
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Dec 25, 2024</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
20 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/async">#async</a></span>
<span>·</span>
<span><a href="/tags/traits">#traits</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/catching-up-with-async-rust" rel="noopener">
<div class="post-summary markup-container "><p data-bo="211">In December 2023, a minor miracle happened: <a href="https://blog.rust-lang.org/2023/12/21/async-fn-rpit-in-traits.html">async fn in traits</a> shipped.</p>
<p data-bo="354">As of Rust 1.39, we already had free-standing async functions:</p>
<figure role="region" aria-label="Rust code block" class="code-block has-language-tag" translate="no" data-lang="rust" data-bo="418"><span class="language-tag" title="Rust"></span><code class="scroll-wrapper"><a-k>pub</a-k> <a-k>async</a-k> <a-k>fn</a-k> <a-f>read_hosts</a-f><a-p>()</a-p> -> eyre<a-p>::</a-p><a-t>Result</a-t><a-p><</a-p><a-t>Vec</a-t><a-p><</a-p><a-t>u8</a-t><a-p>>></a-p> <a-p>{</a-p>
<a-c>// etc.</a-c>
<a-p>}</a-p>
</code></figure><p data-bo="498">…and async functions in impl blocks:</p>
<figure role="region" aria-label="Rust code block" class="code-block has-language-tag" translate="no" data-lang="rust" data-bo="538"><span class="language-tag" title="Rust"></span><code class="scroll-wrapper"><a-k>impl</a-k> <a-t>HostReader</a-t> <a-p>{</a-p>
<a-k>pub</a-k> <a-k>async</a-k> <a-k>fn</a-k> <a-f>read_hosts</a-f><a-p>(</a-p><a-o>&</a-o><a-v>self</a-v><a-p>)</a-p> -> eyre<a-p>::</a-p><a-t>Result</a-t><a-p><</a-p><a-t>Vec</a-t><a-p><</a-p><a-t>u8</a-t><a-p>>></a-p>
</code></figure>
<a id="the-size-of-locals" href="#the-size-of-locals" class="anchor"></a>
<!-- playwall -->
<a id="just-boxing-it" href="#just-boxing-it" class="anchor"></a>
<a id="dynamic-dispatch" href="#dynamic-dispatch" class="anchor"></a>
<a id="dyn-compatibility" href="#dyn-compatibility" class="anchor"></a>
<a id="associated-types" href="#associated-types" class="anchor"></a>
<a id="a-refreshed-service-trait" href="#a-refreshed-service-trait" class="anchor"></a>
<a id="unnameable-types" href="#unnameable-types" class="anchor"></a>
<a id="lifetimes-a-refresher" href="#lifetimes-a-refresher" class="anchor"></a>
<a id="hidden-captures" href="#hidden-captures" class="anchor"></a>
<a id="relaxing-lifetime-bounds" href="#relaxing-lifetime-bounds" class="anchor"></a>
<a id="sendness" href="#sendness" class="anchor"></a>
<a id="afterword" href="#afterword" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/catching-up-with-async-rust" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
data-youtube="OOO-_BCSwiU"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~44ac5ecae8667de6.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~077281962bd0f0aa.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~e91e57590a71ec4d.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~f0d63fc4ca941656.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~27f863ca14730645.jxl 1x,https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~27f863ca14730645.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~800ac5efa9a19cda.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~b256f093d51ff506.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~4314c86becbf9fcf.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~9fdf603e8cac9003.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~032aad6addaf798b.avif 1x,https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~032aad6addaf798b.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~5cbc12cbc70dccdc.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~a90fa4306fa1a3fd.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~450c84ad31c5e80d.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~1861e0fbefde8dfc.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~0d2bb8a5f7199f60.webp 1x,https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~0d2bb8a5f7199f60.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/highlighted-code-in-slides/_thumb~27f863ca14730645.jxl" loading="lazy" width="1920" height="1080" data-kind="media" data-input-path="/content/articles/highlighted-code-in-slides/_thumb.jxl" alt="Thumbnail for Highlighted code in slides"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/highlighted-code-in-slides" rel="noopener">
Highlighted code in slides
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Nov 23, 2024</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
15 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/html">#html</a></span>
<span>·</span>
<span><a href="/tags/css">#css</a></span>
<span>·</span>
<span><a href="/tags/javascript">#javascript</a></span>
<span>·</span>
<span><a href="/tags/color">#color</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/highlighted-code-in-slides" rel="noopener">
<div class="post-summary markup-container "><p data-bo="223">I have obsessed about this long enough, I think it’s only fair I (and you!) get some content out of it.</p>
<p data-bo="328">When I started writing this article, I was working on my <a href="https://p99conf.io">P99 CONF</a> slides.
Those slides happen to include some bits of code. And because I’m a perfectionist, I would like this
code to be syntax highlighted, like this:</p>
<figure role="region" aria-label="Rust code block" class="code-block has-language-tag" translate="no" data-lang="rust" data-bo="568"><span class="language-tag" title="Rust"></span><code class="scroll-wrapper"><a-k>let</a-k> addr<a-p>:</a-p> <a-t>SocketAddr</a-t> = config?
ln = addr?
config
</code></figure>
<a id="not-invented-here" href="#not-invented-here" class="anchor"></a>
<!-- playwall -->
<a id="adding-a-button" href="#adding-a-button" class="anchor"></a>
<a id="computed-styles" href="#computed-styles" class="anchor"></a>
<a id="code-listing" href="#code-listing" class="anchor"></a>
<a id="color-is-hard" href="#color-is-hard" class="anchor"></a>
<a id="closing-thoughts" href="#closing-thoughts" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/highlighted-code-in-slides" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~f24b90a9ba40dfa0.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~56e4ce9bf2f052b7.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~222672a0d5d0d571.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~19bb8e06c2967f18.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~e6499bfb66801fb4.jxl 1x,https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~e6499bfb66801fb4.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~625bfdf295f5b897.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~07f0d1efaaeb5b96.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~263b3786327c649e.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~b61c82b8df14e92d.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~137bc3b0aaa07a22.avif 1x,https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~137bc3b0aaa07a22.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~4e300af42353e822.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~618c0944914de9ea.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~3fb730b7977e33f0.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~6323831a64efedf8.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~8fcc291fdea3089b.webp 1x,https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~8fcc291fdea3089b.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/ktls-now-under-rustls-org/_thumb~e6499bfb66801fb4.jxl" loading="lazy" width="1994" height="1122" data-kind="media" data-input-path="/content/articles/ktls-now-under-rustls-org/_thumb.jxl" alt="Thumbnail for ktls now under the rustls org"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/ktls-now-under-rustls-org" rel="noopener">
ktls now under the rustls org
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Sep 26, 2024</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
3 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rustls">#rustls</a></span>
<span>·</span>
<span><a href="/tags/ktls">#ktls</a></span>
<span>·</span>
<span><a href="/tags/rust">#rust</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/ktls-now-under-rustls-org" rel="noopener">
<div class="post-summary markup-container "><a id="what-s-a-ktls" href="#what-s-a-ktls" class="anchor"><h2>What’s a ktls</h2></a>
<p data-bo="151">I started work on <a href="https://lib.rs/crates/ktls">ktls</a> and <a href="https://lib.rs/crates/ktls-sys">ktls-sys</a>,
a pair of crates exposing <a href="https://www.kernel.org/doc/html/latest/networking/tls-offload.html">Kernel TLS offload</a>
to Rust, about <a href="https://github.com/rustls/ktls/commit/798466d7c3e659ecdf035afac0bea2b679aea4c4">two years ago</a>.</p>
<p data-bo="486">kTLS lets the kernel (and, in turn, any network interface that supports it) take care of encryption, framing,
etc., for the entire duration of a TLS connection… as soon as you <em>have</em> a TLS connection.</p>
<p data-bo="690">For the handshake itself (hellos, change cipher, encrypted extensions,
certificate verification, etc.), you still have to use a userland TLS
implementation.</p>
<a id="the-ktls-api-today" href="#the-ktls-api-today" class="anchor"></a>
<a id="coordinating-collaborating" href="#coordinating-collaborating" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/ktls-now-under-rustls-org" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~89093f6224fce3f3.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~1e68d3e67715fb54.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~caa8fbf8ca833a64.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~3eb43241ba572073.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~641982eb43cbc19f.jxl 1x,https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~641982eb43cbc19f.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~6fefed3933742d31.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~1b68be6264e43184.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~9599a61001e62762.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~a4a384b35f2b6d80.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~988259149c728a7b.avif 1x,https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~988259149c728a7b.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~156ae146cc7c7eda.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~e820e336328dabff.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~fcb7c618dd072540.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~cbbaf56973080684.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~179216f176aab56f.webp 1x,https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~179216f176aab56f.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/state-of-the-fasterthanlime-2024/_thumb~641982eb43cbc19f.jxl" loading="lazy" width="1920" height="1080" data-kind="media" data-input-path="/content/articles/state-of-the-fasterthanlime-2024/_thumb.jxl" alt="Thumbnail for State of the fasterthanlime 2024"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/state-of-the-fasterthanlime-2024" rel="noopener">
State of the fasterthanlime 2024
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Aug 07, 2024</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
17 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/announcement">#announcement</a></span>
<span>·</span>
<span><a href="/tags/meta">#meta</a></span>
<span>·</span>
<span><a href="/tags/ftl-infra">#ftl-infra</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/state-of-the-fasterthanlime-2024" rel="noopener">
<div class="post-summary markup-container "><p data-bo="147">It’s time for some personal <em>and</em> professional news!</p>
<p data-bo="201">TL;DR: I started <a href="https://sdr-podcast.com">a podcast</a> with <a href="https://jamesmunns.com/contact/">James</a>,
I’m stable on antidepressants, I’m giving a <a href="https://www.p99conf.io/">P99 CONF</a> about my <a href="https://github.com/bearcove/fluke">Rust/io_uring/HTTP work</a>,
I’m trying on “they/them” as pronouns, I’m open-sourcing <a href="https://github.com/bearcove/merde_json">merde_json</a>,
<a href="https://github.com/bearcove/rubicon">rubicon</a> and others, I got a divorce in 2023, I found a new business model.</p>
<p data-bo="679">Now that we’re on the same page: let’s unpack this a bit!</p>
<a id="a-podcast-with-james" href="#a-podcast-with-james" class="anchor"></a>
<a id="all-the-personal-news" href="#all-the-personal-news" class="anchor"></a>
<a id="we-re-so-back" href="#we-re-so-back" class="anchor"></a>
<a id="a-new-business-model" href="#a-new-business-model" class="anchor"></a>
<a id="corporate-sponsorships" href="#corporate-sponsorships" class="anchor"></a>
<a id="that-s-it" href="#that-s-it" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/state-of-the-fasterthanlime-2024" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~c4149fb59002425a.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~98f6f82e8e527369.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~8b1774feef70dace.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~ec7d7a16ec13ae8f.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~104c3b5c50f6374c.jxl 1x,https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~104c3b5c50f6374c.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~6ac154429ac55c1f.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~f6a47a0b6125209c.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~1fc404dfe00d59ec.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~3b3e12c58861dedb.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~332e39fa5dbb73b2.avif 1x,https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~332e39fa5dbb73b2.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~41199c101114e94d.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~54869c0fece2a23e.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~234004d67c89bff2.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~f5fcf93f5021d7e5.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~d901653a22ce4b96.webp 1x,https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~d901653a22ce4b96.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/face-cams-the-missing-guide/_thumb~104c3b5c50f6374c.jxl" loading="lazy" width="1920" height="1080" data-kind="media" data-input-path="/content/articles/face-cams-the-missing-guide/_thumb.jxl" alt="Thumbnail for Face cams: the missing guide"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/face-cams-the-missing-guide" rel="noopener">
Face cams: the missing guide
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Mar 02, 2024</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
1 hour 11 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/meta">#meta</a></span>
<span>·</span>
<span><a href="/tags/production">#production</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/face-cams-the-missing-guide" rel="noopener">
<div class="post-summary markup-container "><p data-bo="129">I try to avoid doing “meta” / “behind the scenes” stuff, because I usually feel
like it has to be “earned”. How many YouTube channels are channels about making
YouTube videos? Too many.</p>
<p data-bo="316">Regardless, because I’ve had the opportunity to make my own mistakes now for a
few years (I started <a href="https://www.youtube.com/@fasterthanlime">doing the video thing</a> in earnest in 2019), and because I’ve recently made a few leaps
in quality-of-life re: shooting and editing video, I thought I’d publish a few
notes, if only for reference for my future self.</p>
<a id="where-to-buy-stuff" href="#where-to-buy-stuff" class="anchor"></a>
<a id="about-the-money-thing" href="#about-the-money-thing" class="anchor"></a>
<a id="what-i-m-going-for" href="#what-i-m-going-for" class="anchor"></a>
<a id="microphones-mic-arms" href="#microphones-mic-arms" class="anchor"></a>
<a id="audio-interfaces-32-bit-floating-point" href="#audio-interfaces-32-bit-floating-point" class="anchor"></a>
<a id="studio-headphones" href="#studio-headphones" class="anchor"></a>
<a id="cameras" href="#cameras" class="anchor"></a>
<a id="hdmi-capture-cards" href="#hdmi-capture-cards" class="anchor"></a>
<a id="lighting-frame-rate-flickering" href="#lighting-frame-rate-flickering" class="anchor"></a>
<a id="recording-software" href="#recording-software" class="anchor"></a>
<a id="editing-software" href="#editing-software" class="anchor"></a>
<a id="subtitling-captioning-software" href="#subtitling-captioning-software" class="anchor"></a>
<a id="keyboards-mice-graphic-tablets-misc" href="#keyboards-mice-graphic-tablets-misc" class="anchor"></a>
<a id="secondary-cameras" href="#secondary-cameras" class="anchor"></a>
<a id="storage" href="#storage" class="anchor"></a>
<a id="script-writing-tools" href="#script-writing-tools" class="anchor"></a>
<a id="teleprompter" href="#teleprompter" class="anchor"></a>
<a id="co2-monitor" href="#co2-monitor" class="anchor"></a>
<a id="full-rig-as-of-march-2024" href="#full-rig-as-of-march-2024" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/face-cams-the-missing-guide" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~c76ef15194431923.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~9bac7377dcf44f26.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~4f0a021bfca24efd.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~76ea83d0b40b73c5.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~44b2b0e30d82e9a8.jxl 1x,https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~44b2b0e30d82e9a8.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~d8f02cc780323ba6.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~208984265d23d578.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~48e05d001fafd2f3.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~8ded9b2521a2b2fb.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~f91eade87d83711b.avif 1x,https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~f91eade87d83711b.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~692359fb30d2aba6.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~d47ef784c27f7c7f.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~7c517bc762f06179.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~2947c9a2fbd1f663.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~ea0d020952588d58.webp 1x,https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~ea0d020952588d58.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/just-paying-figma-15-dollars/_thumb~44b2b0e30d82e9a8.jxl" loading="lazy" width="1920" height="1080" data-kind="media" data-input-path="/content/articles/just-paying-figma-15-dollars/_thumb.jxl" alt="Thumbnail for Just paying Figma $15/month because nothing else fucking works"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/just-paying-figma-15-dollars" rel="noopener">
Just paying Figma $15/month because nothing else fucking works
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Oct 19, 2023</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
24 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rant">#rant</a></span>
<span>·</span>
<span><a href="/tags/foss">#foss</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/just-paying-figma-15-dollars" rel="noopener">
<div class="post-summary markup-container "><p data-bo="168">My family wasn’t poor by any stretch of the imagination, but I was raised to
avoid spending money whenever possible.</p>
<p data-bo="286">I was also taught “it’s a poor craftsman that blames their tools”, which
apparently means “take responsibility for your fuckups”, but, to young-me,
definitely sounded more like “you don’t deserve nice things”.</p>
<p data-bo="497">I was also taught from an early age that I was born a sinner, incapable of doing
good by myself, and that all the earthly things were temptations, sent by the
devil to corrupt me (further I guess?) but also temporary, and that I shouldn’t
attach myself.</p>
<a id="draw-io-the-good" href="#draw-io-the-good" class="anchor"></a>
<a id="draw-io-the-bad" href="#draw-io-the-bad" class="anchor"></a>
<a id="figma" href="#figma" class="anchor"></a>
<a id="the-worst-possible-business-strategy-protestant-ethics" href="#the-worst-possible-business-strategy-protestant-ethics" class="anchor"></a>
<a id="penpot" href="#penpot" class="anchor"></a>
<a id="closing-words" href="#closing-words" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/just-paying-figma-15-dollars" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~4591bc324dc98ad2.w400.jxl 1x,https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~7a61e1f716e18ba0.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~fc0bc3fa0a8aac3b.w900.jxl 1x,https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~743a56aaa2df0073.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~a470ce2ad70921c6.jxl 1x,https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~a470ce2ad70921c6.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~f5b5a2244905ad7c.w400.avif 1x,https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~1d1f8437b2cc66c6.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~4a5086f98bbb06c7.w900.avif 1x,https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~8a22b9077692c720.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~20b358107100e30c.avif 1x,https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~20b358107100e30c.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~2cc516955dbbe3a5.w400.webp 1x,https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~624deeb343aa679a.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~f0c08bedc3c646f2.w900.webp 1x,https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~b2c789aa7a0f27bb.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~a5e4801b583715d6.webp 1x,https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~a5e4801b583715d6.webp 2x"><img src="https://cdn.fasterthanli.me/content/articles/cracking-electron-apps-open/_thumb~a470ce2ad70921c6.jxl" loading="lazy" width="1920" height="1080" data-kind="media" data-input-path="/content/articles/cracking-electron-apps-open/_thumb.jxl" alt="Thumbnail for Cracking Electron apps open"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/articles/cracking-electron-apps-open" rel="noopener">
Cracking Electron apps open
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Jul 03, 2023</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
15 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/electron">#electron</a></span>
<span>·</span>
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/asar">#asar</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/articles/cracking-electron-apps-open" rel="noopener">
<div class="post-summary markup-container "><p data-bo="148">I use the <a href="https://github.com/jgraph/drawio-desktop">draw.io desktop app</a> to
make diagrams for my website. I run it on an actual desktop, like Windows or
macOS, but the asset pipeline that converts <code>.drawio</code> files, to <code>.pdf</code>, to
<code>.svg</code>, and then to <code>.svg</code> again (but smaller) runs on Linux.</p>
<p data-bo="440">So I have a Rust program somewhere that opens headless chromium, and loads just
the HTML/JS/CSS part of draw.io I need to render my diagrams, and then use
Chromium’s “print to PDF” functionality to save a PDF.</p>
<a id="windows-installer" href="#windows-installer" class="anchor"></a>
<a id="windows-no-installer" href="#windows-no-installer" class="anchor"></a>
<a id="macos-universal" href="#macos-universal" class="anchor"></a>
<a id="linux-deb" href="#linux-deb" class="anchor"></a>
<a id="linux-rpm" href="#linux-rpm" class="anchor"></a>
<a id="linux-appimage" href="#linux-appimage" class="anchor"></a>
<a id="linux-snap" href="#linux-snap" class="anchor"></a>
<a id="google-chrome-os" href="#google-chrome-os" class="anchor"></a>
<a id="does-this-work-for-any-electron-app" href="#does-this-work-for-any-electron-app" class="anchor"></a>
<a id="figma" href="#figma" class="anchor"></a>
<a id="discord" href="#discord" class="anchor"></a>
<a id="conclusion" href="#conclusion" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/articles/cracking-electron-apps-open" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~a7237bb19a8cdc01.w400.jxl 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~0fb372a1d931ea48.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~f03c4bfe5a31463e.w900.jxl 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~c74d7ac23bd40a03.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~ac757856ca54d4d1.jxl 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~ac757856ca54d4d1.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~e236c51ed4fea2da.w400.avif 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~2228b46daec84999.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~e4a212c010626b7e.w900.avif 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~d049236ffaac69ab.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~a60bd759072a3119.avif 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~a60bd759072a3119.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~b08d75c5fa6d16fe.w400.webp 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~0cbc8f3d547b9ae0.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~abf5e8ed8e39c656.w900.webp 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~646c021f683b00d9.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~6fb2f2b700cf4dbb.webp 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~6fb2f2b700cf4dbb.webp 2x"><img src="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~ac757856ca54d4d1.jxl" loading="lazy" width="1920" height="1081" data-kind="media" data-input-path="/content/series/building-a-rust-service-with-nix/_thumb.jxl" alt="Thumbnail for Extra credit"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/series/building-a-rust-service-with-nix/part-12" rel="noopener">
Extra credit
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Mar 05, 2023</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
9 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/nix">#nix</a></span>
</span>
<span class="indicators">
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/series/building-a-rust-service-with-nix/part-12" rel="noopener">
<div class="post-summary markup-container "><p data-bo="104">We’ve achieved our goals already with this series: we have a web service written
in Rust, built into a Docker image with nix, with a nice dev shell, that we can
deploy to <a href="https://fly.io">fly.io</a>.</p>
<p data-bo="302">But there’s always room for improvement, and so I wanted to talk about a few
things we didn’t bother doing in the previous chapters.</p>
<a id="making-clash-geoip-available-in-the-dev-shell" href="#making-clash-geoip-available-in-the-dev-shell" class="anchor"><h2>Making <code>clash-geoip</code> available in the dev shell</h2></a>
<a id="switching-from-openssl-to-rustls" href="#switching-from-openssl-to-rustls" class="anchor"></a>
<a id="using-docker-compose-to-run-the-service-locally" href="#using-docker-compose-to-run-the-service-locally" class="anchor"></a>
<a id="persisting-the-analytics-database" href="#persisting-the-analytics-database" class="anchor"></a>
<a id="using-sqlite-asynchronously" href="#using-sqlite-asynchronously" class="anchor"></a>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/series/building-a-rust-service-with-nix/part-12" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="frontpage-cta">
<p>There's more where that came from! Check out <a href="/articles">all articles ever</a>.</p>
</div>
</div>
<div class="frontpage-section">
<h2>
Latest series
<a class="sublink" href="/series">View all</a>
</h2>
<div class="post-list">
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~a7237bb19a8cdc01.w400.jxl 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~0fb372a1d931ea48.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~f03c4bfe5a31463e.w900.jxl 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~c74d7ac23bd40a03.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~ac757856ca54d4d1.jxl 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~ac757856ca54d4d1.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~e236c51ed4fea2da.w400.avif 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~2228b46daec84999.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~e4a212c010626b7e.w900.avif 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~d049236ffaac69ab.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~a60bd759072a3119.avif 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~a60bd759072a3119.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~b08d75c5fa6d16fe.w400.webp 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~0cbc8f3d547b9ae0.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~abf5e8ed8e39c656.w900.webp 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~646c021f683b00d9.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~6fb2f2b700cf4dbb.webp 1x,https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~6fb2f2b700cf4dbb.webp 2x"><img src="https://cdn.fasterthanli.me/content/series/building-a-rust-service-with-nix/_thumb~ac757856ca54d4d1.jxl" loading="lazy" width="1920" height="1081" data-kind="media" data-input-path="/content/series/building-a-rust-service-with-nix/_thumb.jxl" alt="Thumbnail for Building a Rust service with Nix"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/series/building-a-rust-service-with-nix" rel="noopener">
Building a Rust service with Nix
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Mar 05, 2023</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
3 hours 1 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/docker">#docker</a></span>
<span>·</span>
<span><a href="/tags/nix">#nix</a></span>
</span>
<span class="indicators">
<span class="complete-indicator">complete</span>
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/series/building-a-rust-service-with-nix" rel="noopener">
<div class="post-summary markup-container "><p data-bo="135">I often give bits and pieces of advice on how to build Rust stuff the comfy way.
But it can be hard to see how everything comes together, especially when it
comes to, say, deploying a web service in production.</p>
<p data-bo="347">So, let’s start from the very beginning (setting up a Linux VM), and march
together towards the objective: a production-grade Rust web service, built with
Nix.</p>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/series/building-a-rust-service-with-nix" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~231dd7f8862417be.w400.jxl 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~bc7d638110c08133.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~26739f67b048b8cf.w900.jxl 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~5d330ab71376ae3c.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~01fb50f782351088.jxl 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~01fb50f782351088.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~eebdec8b40c502ca.w400.avif 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~66ea0214119adaa0.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~f6401f65674b7635.w900.avif 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~0b5827938e201d32.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~60d50306e3849a9b.avif 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~60d50306e3849a9b.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~bebe1806056b7013.w400.webp 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~aad8cfa70a0cc117.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~5d705d14461c7c38.w900.webp 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~db3b2020437c711c.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~60c89dcbe411de53.webp 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~60c89dcbe411de53.webp 2x"><img src="https://cdn.fasterthanli.me/content/series/advent-of-code-2022/_thumb~01fb50f782351088.jxl" loading="lazy" width="1920" height="1081" data-kind="media" data-input-path="/content/series/advent-of-code-2022/_thumb.jxl" alt="Thumbnail for Advent of Code 2022"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/series/advent-of-code-2022" rel="noopener">
Advent of Code 2022
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Dec 02, 2022</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
3 hours 12 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/advent-of-code">#advent-of-code</a></span>
</span>
<span class="indicators">
<span class="complete-indicator">complete</span>
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/series/advent-of-code-2022" rel="noopener">
<div class="post-summary markup-container "><p data-bo="147">Let’s use the <a href="https://adventofcode.com/2022/">Advent of Code
2022</a>, a series of programming challenges
of increasing difficulty, to learn more about the <a href="https://www.rust-lang.org/">Rust programming language</a>.</p>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/series/advent-of-code-2022" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~e190c99c34f9e125.w400.jxl 1x,https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~c8cd65709dc77d4b.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~e503474c229cad5a.w900.jxl 1x,https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~c766280f69f65910.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~ce9dd9e021317a40.jxl 1x,https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~ce9dd9e021317a40.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~2fa966b2b544424f.w400.avif 1x,https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~19caaf32b52bab87.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~d020faca70a258b9.w900.avif 1x,https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~d5c4f7aa4c4fd11b.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~060962e9e476a0d3.avif 1x,https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~060962e9e476a0d3.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~a50c95897902338b.w400.webp 1x,https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~208108ded5f0aa87.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~7ad6b4671873da4f.w900.webp 1x,https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~120404cc67290d4b.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~8ef299419ec1607b.webp 1x,https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~8ef299419ec1607b.webp 2x"><img src="https://cdn.fasterthanli.me/content/series/updating-fasterthanli-me-for-2022/_thumb~ce9dd9e021317a40.jxl" loading="lazy" width="1921" height="1081" data-kind="media" data-input-path="/content/series/updating-fasterthanli-me-for-2022/_thumb.jxl" alt="Thumbnail for Updating fasterthanli.me for 2022"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/series/updating-fasterthanli-me-for-2022" rel="noopener">
Updating fasterthanli.me for 2022
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Nov 15, 2022</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
57 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/webdev">#webdev</a></span>
<span>·</span>
<span><a href="/tags/ftl-infra">#ftl-infra</a></span>
</span>
<span class="indicators">
<span class="complete-indicator">complete</span>
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/series/updating-fasterthanli-me-for-2022" rel="noopener">
<div class="post-summary markup-container "><p data-bo="142">In 2020, I switched from <a href="https://gohugo.io/">a static site
generator</a> to something homemade.</p>
<p data-bo="237">And, as tradition commands, I did <a href="/articles/a-new-website-for-2020">a whole write-up about
it</a>.</p>
<p data-bo="335">Since writing articles and making videos is now <a href="/articles/becoming-fasterthanlime-full-time">my full-time
occupation</a>, I took some time
to upgrade <code>futile</code>, my server software, to the latest and greatest the
Rust ecosystem has to offer.</p>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/series/updating-fasterthanli-me-for-2022" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~936baab8987bd89c.w400.jxl 1x,https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~1eb1108753fa6973.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~d42fefbe714b7660.w900.jxl 1x,https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~4c45ea69d92f8373.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~e35760393be09249.jxl 1x,https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~e35760393be09249.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~a920fbfc4217248d.w400.avif 1x,https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~7b98bfc59ee06dae.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~e025b5557eb8224c.w900.avif 1x,https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~e16957e9754c849e.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~5839a9bfb19f6692.avif 1x,https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~5839a9bfb19f6692.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~42a931913eb7518c.w400.webp 1x,https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~7e5feb9771beb16b.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~f8aa3a010911f2df.w900.webp 1x,https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~4c9c5c1a3ec9a682.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~bb0ffd4ce3e00886.webp 1x,https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~bb0ffd4ce3e00886.webp 2x"><img src="https://cdn.fasterthanli.me/content/series/dont-shell-out/_thumb~e35760393be09249.jxl" loading="lazy" width="1920" height="1081" data-kind="media" data-input-path="/content/series/dont-shell-out/_thumb.jxl" alt="Thumbnail for Don't shell out!"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/series/dont-shell-out" rel="noopener">
Don't shell out!
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Dec 31, 2021</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
1 hour 40 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/image-processing">#image-processing</a></span>
<span>·</span>
<span><a href="/tags/static-linking">#static-linking</a></span>
<span>·</span>
<span><a href="/tags/ftl-infra">#ftl-infra</a></span>
</span>
<span class="indicators">
<span class="complete-indicator">complete</span>
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/series/dont-shell-out" rel="noopener">
<div class="post-summary markup-container "><p data-bo="154">In this series, I change a critical component of this website’s asset pipeline
from “just calling a bunch of external tools” to statically linking with
everything I need to process assets. It involves autoconf, CMake, Meson, CI,
pkg-config, and some code crimes.</p>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/series/dont-shell-out" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~f3f1240714331868.w400.jxl 1x,https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~bfcc6ce933ce0778.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~6dd857bc5e9964d9.w900.jxl 1x,https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~f375553b93e30dbd.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~5253769f778c433a.jxl 1x,https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~5253769f778c433a.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~96a883b5ab779cb3.w400.avif 1x,https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~21f88df3f07145dd.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~d2f5137290c32912.w900.avif 1x,https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~8de98324af719242.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~0aa501b8ad4d5648.avif 1x,https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~0aa501b8ad4d5648.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~010d84a470ddeae4.w400.webp 1x,https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~76673b4da3fd3556.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~3e8a80ed346ae9ea.w900.webp 1x,https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~bf769d2d38280e06.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~f68d3d820e19be4a.webp 1x,https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~f68d3d820e19be4a.webp 2x"><img src="https://cdn.fasterthanli.me/content/series/making-our-own-executable-packer/_thumb~5253769f778c433a.jxl" loading="lazy" width="1920" height="1081" data-kind="media" data-input-path="/content/series/making-our-own-executable-packer/_thumb.jxl" alt="Thumbnail for Making our own executable packer"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/series/making-our-own-executable-packer" rel="noopener">
Making our own executable packer
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Feb 08, 2021</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
8 hours 53 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/os">#os</a></span>
<span>·</span>
<span><a href="/tags/linux">#linux</a></span>
<span>·</span>
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/assembly">#assembly</a></span>
</span>
<span class="indicators">
<span class="complete-indicator">complete</span>
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/series/making-our-own-executable-packer" rel="noopener">
<div class="post-summary markup-container "><p data-bo="147">In this series, we’ll attempt to understand how Linux executables are
organized, how they are executed, and how to make a program that takes an
executable fresh off the linker and compresses it - just because we can.</p>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/series/making-our-own-executable-packer" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~7e637f526a808235.w400.jxl 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~338d902b5dfe5e67.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~ead11916a2b487f9.w900.jxl 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~7a295f5e0f845a78.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~e7c93c440131be20.jxl 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~e7c93c440131be20.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~508610e02a975b02.w400.avif 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~3af95d0c70476187.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~6ea36afb1d840531.w900.avif 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~f5f223df147f8a38.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~4275c219b35c6dca.avif 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~4275c219b35c6dca.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~f810b063f912c2eb.w400.webp 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~35a71de39734a6ea.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~81ee3dfbf5ff9d90.w900.webp 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~c6207991c7cbee98.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~a5ae5b09fd99127a.webp 1x,https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~a5ae5b09fd99127a.webp 2x"><img src="https://cdn.fasterthanli.me/content/series/advent-of-code-2020/_thumb~e7c93c440131be20.jxl" loading="lazy" width="1921" height="1081" data-kind="media" data-input-path="/content/series/advent-of-code-2020/_thumb.jxl" alt="Thumbnail for Advent of Code 2020"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/series/advent-of-code-2020" rel="noopener">
Advent of Code 2020
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Dec 12, 2020</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
2 hours 39 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/advent-of-code">#advent-of-code</a></span>
</span>
<span class="indicators">
<span class="complete-indicator">complete</span>
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/series/advent-of-code-2020" rel="noopener">
<div class="post-summary markup-container "><p data-bo="123">Let’s use the <a href="https://adventofcode.com/2020/">Advent of Code
2020</a>, a series of programming challenges
of increasing difficulty, to learn more about the <a href="https://www.rust-lang.org/">Rust programming language</a>.</p>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/series/advent-of-code-2020" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~2b1be80ec02a8e65.w400.jxl 1x,https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~4bf637bdb6bb4633.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~106f32578e0581c2.w900.jxl 1x,https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~3cf23e71e4357315.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~bd8a628d033066c2.jxl 1x,https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~bd8a628d033066c2.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~e77db6b93509e88a.w400.avif 1x,https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~9d37bab1ce397b79.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~2ade1ff72a9aac23.w900.avif 1x,https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~2b3d23e56076ff77.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~e53957a1220929ab.avif 1x,https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~e53957a1220929ab.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~52d0d6175c05de46.w400.webp 1x,https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~a896d11f0855e3ad.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~b0d4f9d7527ce689.w900.webp 1x,https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~f3cddb61bd52cbb5.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~586f8a04205157da.webp 1x,https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~586f8a04205157da.webp 2x"><img src="https://cdn.fasterthanli.me/content/series/tech-as-seen-on-tv/_thumb~bd8a628d033066c2.jxl" loading="lazy" width="1920" height="1080" data-kind="media" data-input-path="/content/series/tech-as-seen-on-tv/_thumb.jxl" alt="Thumbnail for Technology, as seen on TV"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/series/tech-as-seen-on-tv" rel="noopener">
Technology, as seen on TV
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Oct 28, 2020</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
30 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/tv">#tv</a></span>
</span>
<span class="indicators">
<span class="complete-indicator">complete</span>
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/series/tech-as-seen-on-tv" rel="noopener">
<div class="post-summary markup-container "><p data-bo="133">Enhance! In this series, we’re looking at TV depictions of technology, and
reviewing how realistic they are. Of course, they’re very rarely accurate,
but it’s still interesting to take a look and try to figure out what they
<em>could’ve been thinking of</em>, and just reminisce in general.</p>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/series/tech-as-seen-on-tv" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
<div
class="post-list-item"
>
<div class="post-list-item-inner">
<div class="post-list-thumb">
<picture><source type="image/jxl" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~4343ad3bc0e04922.w400.jxl 1x,https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~a41c2c113db6ebb7.w800.jxl 2x"><source type="image/jxl" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~c8b7708a8a98434f.w900.jxl 1x,https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~f61c67998b4e7dab.w1800.jxl 2x"><source type="image/jxl" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~8e16c037284ba4f9.jxl 1x,https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~8e16c037284ba4f9.jxl 2x"><source type="image/avif" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~d599d7655c9f31ca.w400.avif 1x,https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~85ff14b519e8f22e.w800.avif 2x"><source type="image/avif" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~980a99b344ca6c6f.w900.avif 1x,https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~ac4fbfa1c6784af0.w1800.avif 2x"><source type="image/avif" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~ec71bf21d1d635bd.avif 1x,https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~ec71bf21d1d635bd.avif 2x"><source type="image/webp" media="(max-width: 400px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~9fadc2164f22c7ad.w400.webp 1x,https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~93620d2d11e86403.w800.webp 2x"><source type="image/webp" media="(max-width: 900px)" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~ced8b72b6cb2baa5.w900.webp 1x,https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~5ec9a72e8d959b87.w1800.webp 2x"><source type="image/webp" srcset="https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~c951c259419503e2.webp 1x,https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~c951c259419503e2.webp 2x"><img src="https://cdn.fasterthanli.me/content/series/making-our-own-ping/_thumb~8e16c037284ba4f9.jxl" loading="lazy" width="1920" height="1080" data-kind="media" data-input-path="/content/series/making-our-own-ping/_thumb.jxl" alt="Thumbnail for Making our own ping"></picture>
</div>
<h2 class="post-list-title">
<a class="post-link" href="https://fasterthanli.me/series/making-our-own-ping" rel="noopener">
Making our own ping
</a>
</h2>
<div class="post-blocks">
<div class="post-block small">
<div class="post-metadata">
<div class="post-date">Sep 27, 2019</div>
<span class="reading-time">
<svg id="clock-icon" class="inline-icon" width="1.1em" height="1.1em" style="padding: .1em;" alt="clock icon" enable-background="new 0 0 443.294 443.294" viewBox="0 0 443.294 443.294" width="512" xmlns="http://www.w3.org/2000/svg"><path d="m221.647 0c-122.214 0-221.647 99.433-221.647 221.647s99.433 221.647 221.647 221.647 221.647-99.433 221.647-221.647-99.433-221.647-221.647-221.647zm0 415.588c-106.941 0-193.941-87-193.941-193.941s87-193.941 193.941-193.941 193.941 87 193.941 193.941-87 193.941-193.941 193.941z"></path><path d="m235.5 83.118h-27.706v144.265l87.176 87.176 19.589-19.589-79.059-79.059z"></path></svg>
<abbr title="Estimated reading time, at 220 words per minute, where one word = 5 characters">
4 hours 22 min
</abbr>
</span>
<span class="tags">
<span><a href="/tags/networking">#networking</a></span>
<span>·</span>
<span><a href="/tags/rust">#rust</a></span>
<span>·</span>
<span><a href="/tags/windows">#windows</a></span>
</span>
<span class="indicators">
<span class="complete-indicator">complete</span>
</span>
</div>
</div>
<div class="post-block big">
<a class="post-block-link" href="https://fasterthanli.me/series/making-our-own-ping" rel="noopener">
<div class="post-summary markup-container "><p data-bo="130">When I launched <a href="https://www.patreon.com/fasterthanlime">my Patreon</a>, I vowed
to explain how computers work. But in 2019, computers rarely work in
isolation. So let’s take the time to write a few articles about how
computers talk to each other.</p>
</div>
</a>
<div class="read-more">
<a href="https://fasterthanli.me/series/making-our-own-ping" rel="noopener">
Read more
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="frontpage-cta">
<p>Check out <a href="/series">even more series</a>, if you will.</p>
</div>
</div>
<div class="frontpage-cta" style="text-align: center; border-left: none; border: 1px solid var(--ftl-blue);">
<p>Ever wonder <a href="/about">who's behind all this content?</a></p>
</div>
</div>
</div>
<div class="page-html-spacer"></div>
</main>
</div> <!-- content -->
<div class="nav-bottom">
<div class="nav-content">
<div class="nav-outlinks icons">
<a href="/discord" title="Discord">
<span class="inline-icon-container">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="fi_5968898" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve" width="512" height="512">
<g>
<path d="M433.43,93.222c-32.633-14.973-67.627-26.005-104.216-32.324c-0.666-0.122-1.332,0.183-1.675,0.792 c-4.501,8.005-9.486,18.447-12.977,26.655c-39.353-5.892-78.505-5.892-117.051,0c-3.492-8.39-8.658-18.65-13.179-26.655 c-0.343-0.589-1.009-0.894-1.675-0.792c-36.568,6.298-71.562,17.33-104.216,32.324c-0.283,0.122-0.525,0.325-0.686,0.589 c-66.376,99.165-84.56,195.893-75.64,291.421c0.04,0.467,0.303,0.914,0.666,1.198c43.793,32.161,86.215,51.685,127.848,64.627 c0.666,0.203,1.372-0.04,1.796-0.589c9.848-13.449,18.627-27.63,26.154-42.543c0.444-0.873,0.02-1.909-0.888-2.255 c-13.925-5.282-27.184-11.723-39.939-19.036c-1.009-0.589-1.09-2.032-0.161-2.723c2.684-2.011,5.369-4.104,7.932-6.217 c0.464-0.386,1.11-0.467,1.655-0.224c83.792,38.257,174.507,38.257,257.31,0c0.545-0.264,1.191-0.182,1.675,0.203 c2.564,2.113,5.248,4.226,7.952,6.237c0.928,0.691,0.867,2.134-0.141,2.723c-12.755,7.456-26.014,13.754-39.959,19.016 c-0.908,0.345-1.312,1.402-0.867,2.275c7.689,14.892,16.468,29.073,26.134,42.523c0.404,0.569,1.13,0.813,1.796,0.609 c41.835-12.941,84.257-32.466,128.05-64.627c0.384-0.284,0.626-0.711,0.666-1.178c10.676-110.441-17.881-206.376-75.7-291.421 C433.954,93.547,433.712,93.344,433.43,93.222z M171.094,327.065c-25.227,0-46.014-23.16-46.014-51.604 s20.383-51.604,46.014-51.604c25.831,0,46.417,23.364,46.013,51.604C217.107,303.905,196.723,327.065,171.094,327.065z M341.221,327.065c-25.226,0-46.013-23.16-46.013-51.604s20.383-51.604,46.013-51.604c25.832,0,46.417,23.364,46.014,51.604 C387.235,303.905,367.054,327.065,341.221,327.065z"></path>
</g>
</svg>
</span>
Discord
</a>
<a rel="me" href="https://github.com/sponsors/fasterthanlime" title="GitHub Sponsors" target="_blank">
<span class="inline-icon-container">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
</svg>
</span>
GitHub Sponsors
</a>
<a href="https://patreon.com/fasterthanlime" title="Patreon" target="_blank">
<span class="inline-icon-container">
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1080 1080" style="enable-background:new 0 0 1080 1080;" xml:space="preserve">
<path d="M1033.05,324.45c-0.19-137.9-107.59-250.92-233.6-291.7c-156.48-50.64-362.86-43.3-512.28,27.2 C106.07,145.41,49.18,332.61,47.06,519.31c-1.74,153.5,13.58,557.79,241.62,560.67c169.44,2.15,194.67-216.18,273.07-321.33 c55.78-74.81,127.6-95.94,216.01-117.82C929.71,603.22,1033.27,483.3,1033.05,324.45z"/>
</svg>
</span>
Patreon
</a>
</div>
<div class="nav-outlinks icons">
<a rel="me" href="https://bsky.app/profile/fasterthanli.me" title="Bluesky" target="_blank">
<span class="inline-icon-container">
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="530" viewBox="0 0 600 530"><path fill="#ffffff" d="M135.72 44.03C202.216 93.951 273.74 195.17 300 249.49c26.262-54.316 97.782-155.54 164.28-205.46C512.26 8.009 590-19.862 590 68.825c0 17.712-10.155 148.79-16.111 170.07-20.703 73.984-96.144 92.854-163.25 81.433 117.3 19.964 147.14 86.092 82.697 152.22-122.39 125.59-175.91-31.511-189.63-71.766-2.514-7.38-3.69-10.832-3.708-7.896-.017-2.936-1.193.516-3.707 7.896-13.714 40.255-67.233 197.36-189.63 71.766-64.444-66.128-34.605-132.26 82.697-152.22-67.108 11.421-142.55-7.45-163.25-81.433C20.15 217.613 9.997 86.535 9.997 68.825c0-88.687 77.742-60.816 125.72-24.795z"/></svg>
</span>
Bluesky
</a>
<a rel="me" href="https://hachyderm.io/@fasterthanlime" title="Mastodon" target="_blank">
<span class="inline-icon-container">
<svg width="230.842" height="247.477" viewBox="0 0 216.414 232.01" xmlns="http://www.w3.org/2000/svg"><path style="stroke-width:1.06667" d="M115.057 0C83.418.259 52.984 3.685 35.248 11.83c0 0-35.176 15.735-35.176 69.42 0 12.293-.239 26.992.15 42.58C1.5 176.331 9.848 228.074 58.39 240.922c22.381 5.924 41.598 7.165 57.074 6.314 28.065-1.556 43.82-10.015 43.82-10.015l-.926-20.364s-20.056 6.324-42.58 5.553c-22.316-.765-45.875-2.406-49.484-29.805-.333-2.406-.5-4.98-.5-7.683 0 0 21.907 5.355 49.67 6.627 16.976.778 32.895-.995 49.064-2.924 31.008-3.703 58.007-22.808 61.4-40.266 5.347-27.5 4.907-67.109 4.907-67.109 0-53.685-35.174-69.42-35.174-69.42C177.925 3.685 147.473.26 115.834 0h-.777zM79.25 41.947c13.179 0 23.157 5.066 29.756 15.198l6.416 10.753 6.416-10.753c6.597-10.132 16.576-15.198 29.756-15.198 11.39 0 20.566 4.004 27.574 11.815 6.793 7.81 10.176 18.369 10.176 31.654v65.004H163.59V87.326c0-13.3-5.596-20.05-16.79-20.05-12.375 0-18.577 8.007-18.577 23.841v34.535H102.62V91.117c0-15.834-6.204-23.842-18.58-23.842-11.193 0-16.789 6.751-16.789 20.051v63.094H41.498V85.416c0-13.285 3.383-23.844 10.178-31.654 7.006-7.81 16.183-11.815 27.574-11.815z" transform="scale(.9375)"/></svg>
</span>
Mastodon
</a>
<a href="https://tube.fasterthanli.me" title="PeerTube" target="_blank">
<span class="inline-icon-container">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 16 22">
<path d="M0 0v10.667L8 5.333Z" fill="currentColor" fill-opacity="0.4"/>
<path d="M0 10.667v10.667L8 16Z" fill="currentColor" fill-opacity="0.6"/>
<path d="M8 5.333v10.667L16 10.667Z" fill="currentColor"/>
</svg>
</span>
PeerTube
</a>
<a href="https://youtube.com/@fasterthanlime" title="YouTube" target="_blank">
<span class="inline-icon-container">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"/></svg>
</span>
YouTube
</a>
</div>
<div class="nav-outlinks icons">
<a href="https://www.tiktok.com/@fasterthanlime" title="TikTok" target="_blank">
<span class="inline-icon-container">
<svg id="fi_3046120" enable-background="new 0 0 512 512" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><g><path d="m480.32 128.39c-29.22 0-56.18-9.68-77.83-26.01-24.83-18.72-42.67-46.18-48.97-77.83-1.56-7.82-2.4-15.89-2.48-24.16h-83.47v228.08l-.1 124.93c0 33.4-21.75 61.72-51.9 71.68-8.75 2.89-18.2 4.26-28.04 3.72-12.56-.69-24.33-4.48-34.56-10.6-21.77-13.02-36.53-36.64-36.93-63.66-.63-42.23 33.51-76.66 75.71-76.66 8.33 0 16.33 1.36 23.82 3.83v-62.34-22.41c-7.9-1.17-15.94-1.78-24.07-1.78-46.19 0-89.39 19.2-120.27 53.79-23.34 26.14-37.34 59.49-39.5 94.46-2.83 45.94 13.98 89.61 46.58 121.83 4.79 4.73 9.82 9.12 15.08 13.17 27.95 21.51 62.12 33.17 98.11 33.17 8.13 0 16.17-.6 24.07-1.77 33.62-4.98 64.64-20.37 89.12-44.57 30.08-29.73 46.7-69.2 46.88-111.21l-.43-186.56c14.35 11.07 30.04 20.23 46.88 27.34 26.19 11.05 53.96 16.65 82.54 16.64v-60.61-22.49c.02.02-.22.02-.24.02z"></path></g></svg>
</span>
TikTok
</a>
<a href="https://www.instagram.com/fasterthanlime" title="Instagram" target="_blank">
<span class="inline-icon-container">
<svg height="511pt" viewBox="0 0 511 511.9" width="511pt" xmlns="http://www.w3.org/2000/svg" id="fi_1384031"><path d="m510.949219 150.5c-1.199219-27.199219-5.597657-45.898438-11.898438-62.101562-6.5-17.199219-16.5-32.597657-29.601562-45.398438-12.800781-13-28.300781-23.101562-45.300781-29.5-16.296876-6.300781-34.898438-10.699219-62.097657-11.898438-27.402343-1.300781-36.101562-1.601562-105.601562-1.601562s-78.199219.300781-105.5 1.5c-27.199219 1.199219-45.898438 5.601562-62.097657 11.898438-17.203124 6.5-32.601562 16.5-45.402343 29.601562-13 12.800781-23.097657 28.300781-29.5 45.300781-6.300781 16.300781-10.699219 34.898438-11.898438 62.097657-1.300781 27.402343-1.601562 36.101562-1.601562 105.601562s.300781 78.199219 1.5 105.5c1.199219 27.199219 5.601562 45.898438 11.902343 62.101562 6.5 17.199219 16.597657 32.597657 29.597657 45.398438 12.800781 13 28.300781 23.101562 45.300781 29.5 16.300781 6.300781 34.898438 10.699219 62.101562 11.898438 27.296876 1.203124 36 1.5 105.5 1.5s78.199219-.296876 105.5-1.5c27.199219-1.199219 45.898438-5.597657 62.097657-11.898438 34.402343-13.300781 61.601562-40.5 74.902343-74.898438 6.296876-16.300781 10.699219-34.902343 11.898438-62.101562 1.199219-27.300781 1.5-36 1.5-105.5s-.101562-78.199219-1.300781-105.5zm-46.097657 209c-1.101562 25-5.300781 38.5-8.800781 47.5-8.601562 22.300781-26.300781 40-48.601562 48.601562-9 3.5-22.597657 7.699219-47.5 8.796876-27 1.203124-35.097657 1.5-103.398438 1.5s-76.5-.296876-103.402343-1.5c-25-1.097657-38.5-5.296876-47.5-8.796876-11.097657-4.101562-21.199219-10.601562-29.398438-19.101562-8.5-8.300781-15-18.300781-19.101562-29.398438-3.5-9-7.699219-22.601562-8.796876-47.5-1.203124-27-1.5-35.101562-1.5-103.402343s.296876-76.5 1.5-103.398438c1.097657-25 5.296876-38.5 8.796876-47.5 4.101562-11.101562 10.601562-21.199219 19.203124-29.402343 8.296876-8.5 18.296876-15 29.398438-19.097657 9-3.5 22.601562-7.699219 47.5-8.800781 27-1.199219 35.101562-1.5 103.398438-1.5 68.402343 0 76.5.300781 103.402343 1.5 25 1.101562 38.5 5.300781 47.5 8.800781 11.097657 4.097657 21.199219 10.597657 29.398438 19.097657 8.5 8.300781 15 18.300781 19.101562 29.402343 3.5 9 7.699219 22.597657 8.800781 47.5 1.199219 27 1.5 35.097657 1.5 103.398438s-.300781 76.300781-1.5 103.300781zm0 0"></path><path d="m256.449219 124.5c-72.597657 0-131.5 58.898438-131.5 131.5s58.902343 131.5 131.5 131.5c72.601562 0 131.5-58.898438 131.5-131.5s-58.898438-131.5-131.5-131.5zm0 216.800781c-47.097657 0-85.300781-38.199219-85.300781-85.300781s38.203124-85.300781 85.300781-85.300781c47.101562 0 85.300781 38.199219 85.300781 85.300781s-38.199219 85.300781-85.300781 85.300781zm0 0"></path><path d="m423.851562 119.300781c0 16.953125-13.746093 30.699219-30.703124 30.699219-16.953126 0-30.699219-13.746094-30.699219-30.699219 0-16.957031 13.746093-30.699219 30.699219-30.699219 16.957031 0 30.703124 13.742188 30.703124 30.699219zm0 0"></path></svg>
</span>
Instagram
</a>
<a href="/index.xml" title="RSS" target="_blank">
<span class="inline-icon-container">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M6.503 20.752c0 1.794-1.456 3.248-3.251 3.248-1.796 0-3.252-1.454-3.252-3.248 0-1.794 1.456-3.248 3.252-3.248 1.795.001 3.251 1.454 3.251 3.248zm-6.503-12.572v4.811c6.05.062 10.96 4.966 11.022 11.009h4.817c-.062-8.71-7.118-15.758-15.839-15.82zm0-3.368c10.58.046 19.152 8.594 19.183 19.188h4.817c-.03-13.231-10.755-23.954-24-24v4.812z"/></svg>
</span>
RSS
</a>
</div>
</div>
<div class="nav-content">
<div class="nav-outlinks">
<a href="/about">About</a>
<a href="/legal-notice">Legal Notice</a>
<a href="/privacy-policy">Privacy Policy</a>
<a href="/terms-and-conditions">Terms and Conditions</a>
</div>
</div>
</div> <!-- nav-bottom -->
</div> <!-- body-wrapper -->
<script>
// Fetch video duration from PeerTube API
(function() {
const videoEmbeds = document.querySelectorAll('[data-peertube-id]');
if (!videoEmbeds.length) return;
const formatDuration = (totalSeconds) => {
let remaining = Math.floor(totalSeconds);
const hours = Math.floor(remaining / 3600);
remaining -= hours * 3600;
const mins = Math.floor(remaining / 60);
remaining -= mins * 60;
const secs = Math.floor(remaining);
if (hours > 0) {
return `${hours}h ${mins}m`;
}
return `${mins}m ${secs}s`;
};
videoEmbeds.forEach(async (embed) => {
const videoId = embed.dataset.peertubeId;
if (!videoId) return;
try {
const res = await fetch(`https://tube.fasterthanli.me/api/v1/videos/${videoId}`);
if (!res.ok) return;
const data = await res.json();
// Find the post-list-item container and its metadata
const postItem = embed.closest('.post-list-item');
if (!postItem) return;
const metadata = postItem.querySelector('.post-metadata');
if (!metadata) return;
// Insert duration after the date
const dateEl = metadata.querySelector('.post-date');
if (dateEl) {
const durationEl = document.createElement('span');
durationEl.className = 'video-duration';
durationEl.innerHTML = `<svg class="inline-icon" width="1.1em" height="1.1em" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"/></svg> ${formatDuration(data.duration)}`;
dateEl.after(durationEl);
}
} catch (e) {
console.warn('Failed to fetch video duration:', e);
}
});
})();
</script>
</body>
</html>