<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>juicerblog demo</title>
  <link href="https://juicer.build/themes/juicerblog/demo/feed.xml" rel="self"/>
  <link href="https://juicer.build/themes/juicerblog/demo/"/>
  <id>https://juicer.build/themes/juicerblog/demo/feed.xml</id>
  <updated>2024-12-04T00:00:00Z</updated>
  <author><name>Ed Maxedon</name></author>
  <entry>
    <title>Archive</title>
    <link href="https://juicer.build/themes/juicerblog/demo/archive/"/>
    <id>https://juicer.build/themes/juicerblog/demo/archive/</id>
    <updated>2026-05-27T22:46:01.552523561Z</updated>
    <summary>Every post on this site, grouped by year. The exhaustive list — for the curated front page see /.</summary>
    <content type="html">&lt;p&gt;Every dated post on this site, newest year first. Each year heading also links to the per-year archive at &lt;code&gt;/&amp;lt;year&amp;gt;/&lt;/code&gt; for a richer view (post titles, dates, summaries, reading-time). For per-month archives, follow the month roll-up on any year page.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>About this site</title>
    <link href="https://juicer.build/themes/juicerblog/demo/about/"/>
    <id>https://juicer.build/themes/juicerblog/demo/about/</id>
    <updated>2026-05-27T22:46:01.552523561Z</updated>
    <summary>A tiny demo blog rendered with the juicerblog theme — what it is, who writes it, and what it&apos;s trying to prove.</summary>
    <content type="html">&lt;p&gt;This site exists for one reason: to be a realistic-looking blog so we can iterate on the &lt;strong&gt;juicerblog&lt;/strong&gt; theme without reaching for stock-photo content. Every post here is a real-ish essay about a topic the credited author cares about; nothing is filler, but nothing has to be defended at length either.&lt;/p&gt;
&lt;h4 id=&quot;what-it-exercises&quot;&gt;What it exercises&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tagging&lt;/strong&gt; — most posts carry one or two tags, with &lt;code&gt;meta&lt;/code&gt; deliberately overloaded (used by three posts) and &lt;code&gt;life&lt;/code&gt; used exactly once, so the tag cloud has visible weight differences.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Series&lt;/strong&gt; — the &lt;em&gt;Reading on screens&lt;/em&gt; posts are a three-part series by Alice. The series sidebar lists all three; the prev/next buttons step through chronological order across all posts, regardless of series.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multiple authors&lt;/strong&gt; — Ed, Alice, and Ben each have author records under &lt;code&gt;[[authors]]&lt;/code&gt; in &lt;code&gt;site.toml&lt;/code&gt;. One post (&lt;em&gt;Why static sites still win&lt;/em&gt;) has co-authors.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Date archives&lt;/strong&gt; — &lt;code&gt;dateArchives = true&lt;/code&gt; in &lt;code&gt;site.toml&lt;/code&gt;, so &lt;code&gt;/2024/&lt;/code&gt;, &lt;code&gt;/2024/07/&lt;/code&gt;, &lt;code&gt;/2024/08/&lt;/code&gt;, etc., land as their own pages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aliases&lt;/strong&gt; — &lt;em&gt;Why static sites still win&lt;/em&gt; declares two old URLs that resolve via meta-refresh.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Permalinks&lt;/strong&gt; — &lt;code&gt;[permalinks] posts = &amp;quot;:year/:month/:slug/&amp;quot;&lt;/code&gt; — every post lives under its date, so the URL survives a re-tagging.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Atom feeds&lt;/strong&gt; — &lt;code&gt;/feed.xml&lt;/code&gt; aggregates everything; per-section feeds drop in too.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;why-a-third-demo-blog&quot;&gt;Why a third demo blog&lt;/h4&gt;
&lt;p&gt;Two reasons. First, a theme is only as good as the content you can iterate on, and stock-Lorem-ipsum hides exactly the design problems that show up in real text — tag cloud imbalance, series sidebars with awkward title lengths, multi-author bylines that need to wrap, posts with figures vs. without. Second, every Phase-2 engine feature ships with a layout in juicerblog, and a layout that has no demo content is a layout that breaks at the next refactor without anybody noticing.&lt;/p&gt;
&lt;h4 id=&quot;how-a-page-is-different-from-a-post&quot;&gt;How a “page” is different from a “post”&lt;/h4&gt;
&lt;p&gt;This page declares &lt;code&gt;static: true&lt;/code&gt; in its frontmatter, which tells the juicerblog theme to drop the post chrome (date line, reading time, tags, series sidebar, prev/next nav) and render the body as a clean long-form essay. The signal is purely a theme convention — the engine still treats this file like any other content — but it means an about / colophon / contact page can live alongside the post archive without looking like part of it.&lt;/p&gt;
&lt;p&gt;Source for the demo lives at &lt;code&gt;examples/blog-site/&lt;/code&gt; in the &lt;a href=&quot;https://github.com/edadma/juicer&quot;&gt;juicer repo&lt;/a&gt;. Pull requests welcome.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Why static sites still win</title>
    <link href="https://juicer.build/themes/juicerblog/demo/why-static/"/>
    <id>https://juicer.build/themes/juicerblog/demo/why-static/</id>
    <updated>2024-12-04T00:00:00Z</updated>
    <summary>Generated HTML is fast, cheap, and ages well. A short defence of the boring choice.</summary>
    <content type="html">&lt;p&gt;A static site generator turns markdown + templates into HTML at build time. No runtime database, no app server, no per-request rendering — the bytes are just &lt;em&gt;there&lt;/em&gt;, ready to be served by any file host that knows what a directory looks like.&lt;/p&gt;
&lt;h4 id=&quot;the-boring-case&quot;&gt;The boring case&lt;/h4&gt;
&lt;p&gt;It’s hard to overstate how good this story is in 2024. CDNs are everywhere; the marginal cost of serving a request from cache is essentially zero. There’s no scaling story to plan for, no failover to design, no security patches to chase down at 3 AM because some CMS plugin opened a hole.&lt;/p&gt;
&lt;p&gt;You write markdown, you push to git, the site updates. That’s the whole deployment story.&lt;/p&gt;
&lt;h4 id=&quot;the-ageing-case&quot;&gt;The ageing case&lt;/h4&gt;
&lt;p&gt;A WordPress install from 2014 is a forensic exercise in 2024. A static HTML directory from 2014 still serves its content. The format is the format; browsers haven’t lost the ability to render &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When the next paradigm shift hits — and there will be one — your static site keeps working. That’s not nothing.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>A whirlwind tour of Scala 3</title>
    <link href="https://juicer.build/themes/juicerblog/demo/scala-3-tour/"/>
    <id>https://juicer.build/themes/juicerblog/demo/scala-3-tour/</id>
    <updated>2024-11-18T00:00:00Z</updated>
    <summary>Five things Scala 3 gets right, illustrated with the smallest examples that make the case.</summary>
    <content type="html">&lt;p&gt;Scala 3 cleans up a decade of accreted complexity. Five things land squarely:&lt;/p&gt;
&lt;h4 id=&quot;significant-indentation&quot;&gt;Significant indentation&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;hl-keyword&quot;&gt;var&lt;/span&gt; value&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;):&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;def&lt;/span&gt; map&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;](&lt;/span&gt;f&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;U&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;hl-type&quot;&gt;Box&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;hl-punctuation&quot;&gt;))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Curly braces are still legal, but most code reads better without them. The compiler accepts both styles — pick what fits.&lt;/p&gt;
&lt;h4 id=&quot;enums-are-first-class&quot;&gt;Enums are first-class&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Obj&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;fields&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Arr&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;elements&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Json&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;])&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Str&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Num&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;BigDecimal&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Boolean&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Null&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A real algebraic-data-type syntax. Pattern matching gets exhaustiveness checking automatically.&lt;/p&gt;
&lt;h4 id=&quot;given-using-replaces-implicit&quot;&gt;Given / using replaces implicit&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;trait&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;]:&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;def&lt;/span&gt; show&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;String&lt;/span&gt;

&lt;span class=&quot;hl-keyword&quot;&gt;given&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;with&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;def&lt;/span&gt; show&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; n&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;toString

&lt;span class=&quot;hl-keyword&quot;&gt;def&lt;/span&gt; render&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;](&lt;/span&gt;t&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;hl-keyword&quot;&gt;using&lt;/span&gt; s&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;Show&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;hl-type&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;]):&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; s&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;show&lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;t&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The intent reads off the page now: &lt;code&gt;given&lt;/code&gt; introduces an instance, &lt;code&gt;using&lt;/code&gt; consumes one.&lt;/p&gt;
&lt;h4 id=&quot;extension-methods&quot;&gt;Extension methods&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-scala&quot;&gt;&lt;span class=&quot;hl-keyword&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;hl-punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;hl-punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;hl-keyword&quot;&gt;def&lt;/span&gt; shout&lt;span class=&quot;hl-punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hl-type&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;hl-keyword&quot;&gt;=&lt;/span&gt; s&lt;span class=&quot;hl-punctuation&quot;&gt;.&lt;/span&gt;toUpperCase &lt;span class=&quot;hl-keyword&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;hl-string&quot;&gt;&amp;quot;!&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cleaner than the implicit-class song-and-dance Scala 2 made you do.&lt;/p&gt;
&lt;h4 id=&quot;match-types-and-inline&quot;&gt;Match types and inline&lt;/h4&gt;
&lt;p&gt;The advanced features (match types, transparent inline, capture checking) round out a language that finally fits in your head.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Markdown is enough</title>
    <link href="https://juicer.build/themes/juicerblog/demo/markdown-power/"/>
    <id>https://juicer.build/themes/juicerblog/demo/markdown-power/</id>
    <updated>2024-10-30T00:00:00Z</updated>
    <summary>Plain-text markup turned out to be the right level of abstraction for the writing web.</summary>
    <content type="html">&lt;p&gt;Twenty years of WYSIWYG editors lost to a syntax invented for read-this-as-text emails. The lesson, in retrospect, is obvious: &lt;strong&gt;text is the universal interchange format&lt;/strong&gt;, and markdown is the smallest possible layer of structure on top of it.&lt;/p&gt;
&lt;h4 id=&quot;why-markdown-won&quot;&gt;Why markdown won&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;A specification readable by ten-year-olds. A toolchain that runs in any language. Diffs that highlight prose, not bracket-soup.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can read a markdown file as plain text and never miss a thing. You can also render it to HTML, PDF, an EPUB, a man page. The format encodes intent (&lt;code&gt;# Heading&lt;/code&gt;, &lt;code&gt;**bold**&lt;/code&gt;) without committing to a presentation.&lt;/p&gt;
&lt;h4 id=&quot;what-it-isn-t&quot;&gt;What it isn’t&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Not a layout language. Use HTML or CSS for that.&lt;/li&gt;
&lt;li&gt;Not a programming language. No conditionals, no loops, no data flow.&lt;/li&gt;
&lt;li&gt;Not WYSIWYG. The preview is downstream of the source.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These limits are what makes markdown durable. Add a third comma and you get reST; add a fourth and you get TeX. Each step toward power is a step away from “anyone can author this on a phone.”&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Typography 101 for site builders</title>
    <link href="https://juicer.build/themes/juicerblog/demo/typography-101/"/>
    <id>https://juicer.build/themes/juicerblog/demo/typography-101/</id>
    <updated>2024-09-22T00:00:00Z</updated>
    <summary>A short opinionated guide to picking type, sizing it, and not embarrassing yourself.</summary>
    <content type="html">&lt;p&gt;Most sites get type wrong by default — too cramped, too small, too many faces fighting for attention. The fixes are mostly free.&lt;/p&gt;
&lt;h4 id=&quot;pick-two&quot;&gt;Pick two&lt;/h4&gt;
&lt;p&gt;One serif, one sans. That’s it. A monospace for code if there is code. The discipline of “two faces, two roles” eliminates 90% of typographic clutter.&lt;/p&gt;
&lt;h4 id=&quot;set-a-generous-measure&quot;&gt;Set a generous measure&lt;/h4&gt;
&lt;p&gt;Reading prose at 100 characters per line is exhausting; 60–75 is comfortable. Set &lt;code&gt;max-width: 38rem&lt;/code&gt; on the column and stop fighting your eyes.&lt;/p&gt;
&lt;h4 id=&quot;line-height-is-doing-more-than-you-think&quot;&gt;Line-height is doing more than you think&lt;/h4&gt;
&lt;p&gt;Body text wants &lt;code&gt;line-height: 1.6&lt;/code&gt; to &lt;code&gt;1.75&lt;/code&gt;. Headings want closer to &lt;code&gt;1.15&lt;/code&gt;. Buttons and labels want &lt;code&gt;1.0&lt;/code&gt;. The vertical rhythm of a page comes from these ratios more than from any specific font.&lt;/p&gt;
&lt;h4 id=&quot;trust-system-stacks&quot;&gt;Trust system stacks&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;font-family: &amp;quot;Iowan Old Style&amp;quot;, Charter, Georgia, serif;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The web safe stack of 2010 still works in 2024. You don’t need to ship a 200KB webfont to look professional.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>A short note on file naming</title>
    <link href="https://juicer.build/themes/juicerblog/demo/file-naming-note/"/>
    <id>https://juicer.build/themes/juicerblog/demo/file-naming-note/</id>
    <updated>2024-09-03T00:00:00Z</updated>
    <summary>Kebab-case, lowercase, no dates in the filename, and never use a space. Five years of regret in one paragraph.</summary>
    <content type="html">&lt;p&gt;Kebab-case. Lowercase. No dates in the filename — that’s what frontmatter is for. Never use a space, never use a colon (Windows hates you back), and treat anything past 50 characters as a smell. The slug is the URL is the canonical handle for the rest of the post’s life; pick something a stranger could reasonably guess.&lt;/p&gt;
&lt;p&gt;Five years of regret distilled into one paragraph.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>On coffee rituals</title>
    <link href="https://juicer.build/themes/juicerblog/demo/coffee-rituals/"/>
    <id>https://juicer.build/themes/juicerblog/demo/coffee-rituals/</id>
    <updated>2024-08-15T00:00:00Z</updated>
    <summary>A small daily practice with a hardware budget, a chemistry, and an entire morning baked in.</summary>
    <content type="html">&lt;p&gt;The water comes to a boil while the beans grind. The grinder is loud, then quiet; the kettle is quiet, then quiet differently. The shape of the morning condenses around 30 seconds of sound and 4 minutes of waiting.&lt;/p&gt;
&lt;h4 id=&quot;the-ritual&quot;&gt;The ritual&lt;/h4&gt;
&lt;p&gt;Bloom: 30 grams of grounds, 60 grams of water, 30 seconds of stirring while the puck off-gasses. Pour to 200, then 350, then 500. Stop the bed from collapsing. Wait. Drink.&lt;/p&gt;
&lt;p&gt;The coffee almost doesn’t matter at this point. The ritual is the thing.&lt;/p&gt;
&lt;h4 id=&quot;why-morning&quot;&gt;Why morning&lt;/h4&gt;
&lt;p&gt;The first hour after waking is where most days are won or lost. A practice that demands attention — even a low-stakes one — anchors the rest. Easier to focus on something hard at 9 AM if you’ve already focused on something deliberate at 7.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Reading on screens, part 3: long-form reading patterns</title>
    <link href="https://juicer.build/themes/juicerblog/demo/reading-on-screens-3/"/>
    <id>https://juicer.build/themes/juicerblog/demo/reading-on-screens-3/</id>
    <updated>2024-08-05T00:00:00Z</updated>
    <summary>People scan first and read second. The article that survives that first scan is the one that gets read. Eight design moves that survive the scan.</summary>
    <content type="html">&lt;p&gt;Eye-tracking studies on long-form web reading converge on the same boring conclusion: the first thing your reader does is &lt;em&gt;scan&lt;/em&gt;. They glance at the title, fall to the first paragraph, jump down to scan headings, scroll the bar to gauge length, scroll back up, and only then commit to reading.&lt;/p&gt;
&lt;p&gt;If your article doesn’t survive that scan, it doesn’t get read. The encouraging news is that “surviving the scan” is mostly a structural problem, not a writing one.&lt;/p&gt;
&lt;h4 id=&quot;1-front-load-the-thesis&quot;&gt;1. Front-load the thesis&lt;/h4&gt;
&lt;p&gt;The first sentence is the only sentence you can guarantee gets read. It should answer: &lt;em&gt;what is this article about, and why should I keep going?&lt;/em&gt; Burying the lede past a paragraph of throat-clearing is the single most common failure mode of essays that “didn’t take off.”&lt;/p&gt;
&lt;p&gt;Compare:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’ve been thinking about how people read on screens lately, ever since I noticed that…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;vs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;People scan first and read second. The article that survives that first scan is the one that gets read.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The second version costs you the warm-up. It buys you the reader.&lt;/p&gt;
&lt;h4 id=&quot;2-scannable-headings&quot;&gt;2. Scannable headings&lt;/h4&gt;
&lt;p&gt;Your headings should make sense read in isolation. A reader scrolling past should be able to reconstruct the article’s argument from the headings alone. “A note on history” is decorative; “Why the Greek alphabet won” is structural.&lt;/p&gt;
&lt;p&gt;The test: copy your article’s headings into a new document. Do they form a coherent outline?&lt;/p&gt;
&lt;h4 id=&quot;3-the-38-rem-column&quot;&gt;3. The 38-rem column&lt;/h4&gt;
&lt;p&gt;Comfortable reading hits 60–75 characters per line. At a body font size of 17–18 px, that’s 38–42 rem. Wider columns force the eye to track too far horizontally and lose the line break; narrower columns produce too many line breaks per minute and the eye fatigues.&lt;/p&gt;
&lt;p&gt;The web’s instinct to fill the viewport horizontally is a UI-design instinct, not a reading instinct. Reading wants the column to be small.&lt;/p&gt;
&lt;h4 id=&quot;4-small-inline-contrast&quot;&gt;4. Small inline contrast&lt;/h4&gt;
&lt;p&gt;Italic and bold are the two pieces of structural emphasis that survive the scan. They mark &lt;em&gt;this is a definition&lt;/em&gt;, &lt;em&gt;this is the key word&lt;/em&gt;, &lt;em&gt;this is the contradiction I’m flagging&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Use them sparingly. A page with five bolded phrases pulls the eye to all five and the eye trusts none of them. A page with one bolded phrase per scroll-screen makes that phrase the load-bearing claim.&lt;/p&gt;
&lt;h4 id=&quot;5-lists-for-parallel-structure&quot;&gt;5. Lists for parallel structure&lt;/h4&gt;
&lt;p&gt;Lists are good when items are parallel:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Subject parallel.&lt;/strong&gt; “Three things designers get wrong about color.”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Form parallel.&lt;/strong&gt; Each item begins with a verb in the same tense.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Length parallel.&lt;/strong&gt; Items don’t vary by 10x in word count.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lists are bad when forced. If your three “items” are really one big idea broken into three sentences, write the sentences. The reader will follow.&lt;/p&gt;
&lt;h4 id=&quot;6-code-blocks-as-visual-anchors&quot;&gt;6. Code blocks as visual anchors&lt;/h4&gt;
&lt;p&gt;Even a non-programmer reader uses code blocks as scroll waypoints. The reader scrolls, sees a code block, registers “technical content here,” and may or may not stop. Make sure the prose around your code block stands on its own — readers who skip code should still come away with the argument.&lt;/p&gt;
&lt;p&gt;This means: no “as you can see in the code above” phrasing. Restate the point in prose immediately after.&lt;/p&gt;
&lt;h4 id=&quot;7-pull-quotes-earn-their-keep&quot;&gt;7. Pull quotes earn their keep&lt;/h4&gt;
&lt;p&gt;A pull quote that just repeats a sentence from the body is decorative. A pull quote that &lt;em&gt;isolates a claim&lt;/em&gt; and gives the eye a place to land while scrolling is structural.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The unspoken floor for “comfortable long-form reading” is closer to 8–13:1 contrast — well above WCAG AA.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That’s a pull quote. It commits to a claim, in language that survives being lifted out of context.&lt;/p&gt;
&lt;h4 id=&quot;8-end-with-a-turn&quot;&gt;8. End with a turn&lt;/h4&gt;
&lt;p&gt;The final paragraph should turn the article into a question, a recommendation, or a stake. Don’t summarize what you just said — the reader was there. Move the conversation forward.&lt;/p&gt;
&lt;p&gt;This series ran three parts: the substrate (subpixels and hinting), the chemistry (color and dark mode), and the choreography (how the eye moves through long-form). The next move, for any one essay, is yours: open the document and look at it for thirty seconds without reading it. What did your eye do? &lt;em&gt;That’s&lt;/em&gt; what your reader is doing too.&lt;/p&gt;</content>
  </entry>
  <entry>
    <title>Reading on screens, part 2: color, contrast, and dark mode</title>
    <link href="https://juicer.build/themes/juicerblog/demo/reading-on-screens-2/"/>
    <id>https://juicer.build/themes/juicerblog/demo/reading-on-screens-2/</id>
    <updated>2024-07-22T00:00:00Z</updated>
    <summary>WCAG ratios are a floor, not a ceiling. Why &quot;pure black on pure white&quot; fatigues your eye, and what to do instead.</summary>
    <content type="html">&lt;p&gt;The default body color of every browser is &lt;code&gt;#000000&lt;/code&gt; on &lt;code&gt;#ffffff&lt;/code&gt;. Maximum contrast, right? That’s actually the problem.&lt;/p&gt;
&lt;h4 id=&quot;pure-black-is-a-glare-problem&quot;&gt;Pure black is a glare problem&lt;/h4&gt;
&lt;p&gt;Sunlight hitting paper bounces back diffusely; sunlight (or backlight) coming &lt;em&gt;through&lt;/em&gt; a screen punches into your eye directly. When the brightest part of the screen is pure white and the darkest is pure black, the dynamic range your eye is asked to process is roughly the same as standing in a snowfield staring at a wet rock. Reduce both ends and the eye relaxes.&lt;/p&gt;
&lt;p&gt;Most production type uses &lt;strong&gt;near-white background&lt;/strong&gt; (&lt;code&gt;#fcfcfa&lt;/code&gt;, &lt;code&gt;#f8f7f4&lt;/code&gt;, the famous &lt;code&gt;#fdfcf8&lt;/code&gt; of paperback novels) and &lt;strong&gt;near-black foreground&lt;/strong&gt; (&lt;code&gt;#1f1f1f&lt;/code&gt;, &lt;code&gt;#1c1917&lt;/code&gt;):&lt;/p&gt;
&lt;figure&gt;
  &lt;div style=&quot;display:grid;grid-template-columns:1fr 1fr;gap:1rem;font-family:Georgia,serif;line-height:1.5&quot;&gt;
    &lt;div style=&quot;background:#fff;color:#000;padding:1rem;border:1px solid #ccc&quot;&gt;
      &lt;strong&gt;Pure black on pure white&lt;/strong&gt;&lt;br&gt;
      The default. Notice how your eye flickers around the edges as it tries to settle on the column.
    &lt;/div&gt;
    &lt;div style=&quot;background:#fdfcf8;color:#1c1917;padding:1rem;border:1px solid #ccc&quot;&gt;
      &lt;strong&gt;Warm cream on deep ink&lt;/strong&gt;&lt;br&gt;
      Same letterforms; the eye lands and stays. The contrast ratio is still 13:1 — well above WCAG AAA.
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;figcaption&gt;Same words, two palettes. Read each side for thirty seconds and you&apos;ll feel the difference.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;wcag-ratios-are-necessary-but-not-sufficient&quot;&gt;WCAG ratios are necessary but not sufficient&lt;/h4&gt;
&lt;p&gt;WCAG AA wants 4.5:1 for body text; AAA wants 7:1. Hit those, and you’ve cleared the &lt;em&gt;accessibility&lt;/em&gt; bar. You have not necessarily produced text that’s pleasant to read for an hour.&lt;/p&gt;
&lt;p&gt;The unspoken floor for “comfortable long-form reading” is closer to &lt;strong&gt;8–13:1&lt;/strong&gt; with &lt;strong&gt;off-white&lt;/strong&gt; backgrounds:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Foreground&lt;/th&gt;&lt;th&gt;Background&lt;/th&gt;&lt;th&gt;Ratio&lt;/th&gt;&lt;th&gt;Verdict&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;#000&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;#fff&lt;/code&gt;&lt;/td&gt;&lt;td&gt;21.0&lt;/td&gt;&lt;td&gt;Glare-prone&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;#1c1917&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;#fdfcf8&lt;/code&gt;&lt;/td&gt;&lt;td&gt;16.7&lt;/td&gt;&lt;td&gt;Cream-paper feel&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;#44403c&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;#fdfcf8&lt;/code&gt;&lt;/td&gt;&lt;td&gt;8.9&lt;/td&gt;&lt;td&gt;Pleasant for body&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;#78716c&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;#fdfcf8&lt;/code&gt;&lt;/td&gt;&lt;td&gt;4.7&lt;/td&gt;&lt;td&gt;Edge of legibility&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The 4.7 row meets WCAG AA. Don’t put your body text there.&lt;/p&gt;
&lt;h4 id=&quot;dark-mode-is-its-own-problem&quot;&gt;Dark mode is its own problem&lt;/h4&gt;
&lt;p&gt;Inverting the colors does not, in fact, give you a dark mode. You have to redesign:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Reduce, don’t invert.&lt;/strong&gt; A dark background fights pure white text just as hard as a white background fights black. Pull both toward grey.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Desaturate accent colors.&lt;/strong&gt; The &lt;code&gt;#c2410c&lt;/code&gt; amber that anchors a light theme will burn in a dark one. Use a lighter, slightly cooler tone (&lt;code&gt;#fb923c&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Watch your borders.&lt;/strong&gt; A 1px hairline that read as “subtle separator” on cream paper will &lt;em&gt;vanish&lt;/em&gt; on a dark background. Either make it lighter relative to the bg, or replace it with negative space.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Think about your shadows.&lt;/strong&gt; They mostly stop working. Borders or elevation tokens replace them.&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;
  &lt;div style=&quot;display:grid;grid-template-columns:1fr 1fr;gap:1rem&quot;&gt;
    &lt;div style=&quot;background:#000;color:#fff;padding:1rem;border-radius:4px&quot;&gt;
      &lt;strong style=&quot;color:#ff6347&quot;&gt;Pure white on pure black&lt;/strong&gt;&lt;br&gt;
      Fonts visibly bleed into the background. The accent color burns.
    &lt;/div&gt;
    &lt;div style=&quot;background:#1c1917;color:#fafaf9;padding:1rem;border-radius:4px&quot;&gt;
      &lt;strong style=&quot;color:#fb923c&quot;&gt;Off-white on warm ink&lt;/strong&gt;&lt;br&gt;
      Your eye relaxes. The accent reads as warm, not neon.
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;figcaption&gt;Same idea, dark side. Notice how the right column doesn&apos;t shimmer.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id=&quot;contrast-for-code&quot;&gt;Contrast for code&lt;/h4&gt;
&lt;p&gt;Code blocks are often where dark-mode design falls apart, because syntax highlighting was designed for light backgrounds. Pull the comment-grey &lt;em&gt;up&lt;/em&gt;, the keyword color toward warmer tones, and the background slightly darker than the body so the block reads as a distinct surface:&lt;/p&gt;
&lt;dl&gt;
  &lt;dt&gt;```css&lt;/dt&gt;
  &lt;dd&gt;
&lt;p&gt;root[data-theme=”dark”] {&lt;/p&gt;  &lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;–code-bg:    #161412;          /* darker than body’s #1c1917 &lt;em&gt;/
–code-text:  #e5e5e5;
–syn-keyword: #fb923c;         /&lt;/em&gt; warm, not neon &lt;em&gt;/
–syn-string:  #84cc16;         /&lt;/em&gt; lime, not pure green &lt;em&gt;/
–syn-comment: #78716c;         /&lt;/em&gt; up from #57534e */
}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
Final part: long-form reading patterns. How people actually move through 2,000 words.
&lt;/code&gt;&lt;/pre&gt;</content>
  </entry>
  <entry>
    <title>Reading on screens, part 1: display fundamentals</title>
    <link href="https://juicer.build/themes/juicerblog/demo/reading-on-screens-1/"/>
    <id>https://juicer.build/themes/juicerblog/demo/reading-on-screens-1/</id>
    <updated>2024-07-08T00:00:00Z</updated>
    <summary>Subpixel rendering, anti-aliasing, and hinting — the substrate every screen-typography decision rests on.</summary>
    <content type="html">&lt;p&gt;Before we can reason about line-height or letter-spacing, we need to be honest about what we’re rendering &lt;em&gt;into&lt;/em&gt;. A “pixel” is a triplet of red-green-blue subpixels arranged in a known geometry, and most operating systems exploit that geometry to triple horizontal resolution at the cost of color fringing.&lt;/p&gt;
&lt;h4 id=&quot;rgb-stripe-vs-pentile-vs-nothing&quot;&gt;RGB stripe vs. PenTile vs. nothing&lt;/h4&gt;
&lt;p&gt;Desktop monitors are overwhelmingly &lt;strong&gt;RGB stripe&lt;/strong&gt; — three vertical bars per logical pixel:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[R][G][B]   [R][G][B]   [R][G][B]
[R][G][B]   [R][G][B]   [R][G][B]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;OLED phones often use &lt;strong&gt;PenTile&lt;/strong&gt; layouts where greens outnumber reds and blues. The “300 PPI iPhone display” and the “300 PPI laptop display” do not have the same effective resolution for thin vertical strokes, and your fonts will look subtly different on each.&lt;/p&gt;
&lt;p&gt;When the OS draws a glyph, it can target subpixel positions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fn draw_stem(x: f32, y: f32, height: f32) {
    // x is fractional in physical pixels — 0.33 lights the green
    // sub-pixel only; 0.67 lights blue. Whole numbers light all three.
    rasterize(x, y, /*width=*/1.0, height);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The catch: subpixel rendering only works when you know the subpixel layout. Rotate the display 90° and the technique inverts; on a phone in landscape it usually disables itself.&lt;/p&gt;
&lt;h4 id=&quot;anti-aliasing&quot;&gt;Anti-aliasing&lt;/h4&gt;
&lt;p&gt;A glyph’s edge rarely lands on a pixel boundary. Anti-aliasing samples the glyph’s coverage of each pixel and renders accordingly:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Coverage&lt;/th&gt;&lt;th&gt;Pixel value&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;0%&lt;/td&gt;&lt;td&gt;background&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;25%&lt;/td&gt;&lt;td&gt;0.75 background + 0.25 ink&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;50%&lt;/td&gt;&lt;td&gt;0.50 / 0.50&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;75%&lt;/td&gt;&lt;td&gt;0.25 / 0.75&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;100%&lt;/td&gt;&lt;td&gt;ink&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The “fuzziness” people complain about with non-Retina displays is anti-aliased coverage doing exactly what it’s supposed to do, just at a resolution where 25% coverage is half a millimetre wide and your eye notices.&lt;/p&gt;
&lt;h4 id=&quot;hinting&quot;&gt;Hinting&lt;/h4&gt;
&lt;p&gt;Hinting is the font’s attempt to round its outlines to the pixel grid so that a stem ends &lt;em&gt;exactly&lt;/em&gt; at a pixel boundary. Done well, hinting makes 12px Verdana look like a deliberate design choice instead of a bitmap accident. Done badly — or skipped entirely on a Mac, which doesn’t hint — it’s the difference between text that “snaps” into shape at small sizes and text that visibly blurs.&lt;/p&gt;
&lt;p&gt;Most modern setups have given up on hinting because Retina-class densities (&amp;gt;200 PPI) make pixel-level snapping invisible. Outside that regime — every CRT, every old laptop, every projector — hinting is still load-bearing, and your designer-mac-rendered comp will not match.&lt;/p&gt;
&lt;h4 id=&quot;what-it-means-for-the-css-you-write&quot;&gt;What it means for the CSS you write&lt;/h4&gt;
&lt;p&gt;You don’t get to control any of this. You can decide whether to hide it or design with it in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Choose a body font that ships well-hinted (Charter, Source Serif, Inter) over one that doesn’t (most decorative serifs).&lt;/li&gt;
&lt;li&gt;Avoid 1px-wide vertical lines next to text — they alias differently than the glyph stems do.&lt;/li&gt;
&lt;li&gt;Test on a non-Retina monitor at least once. The rendering you see is what 30% of your audience sees.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next part: color, contrast, and the dark-mode rabbit hole.&lt;/p&gt;</content>
  </entry>
</feed>
