This post is intentionally long.
It exists for two reasons:
- To make it obvious when a layout is too narrow.
- To test that reading mode truly feels like a full-window experience (including long scrolling).
If you’re reading this inside the site:
- Press ⌘F / Ctrl F to enter reading mode.
- Press Esc (or click the “exit” button) to leave.
- Try the command bar:
open "reading mode"(fuzzy match) orcd blog.
This is a sample post. Delete it when you’re done testing.
A quick terminal cheat sheet
# Navigation
./home
./blog
./about
./contact
# Move "up" contextually
cd..
# Go to a page
cd blog
cd about
# Open a post by fuzzy title
open "reading mode"
open reading
# Jump to a tag or series
cd "#react"
cd "series:stack-notes"Readability: short lines vs long lines
A good reading layout should handle both:
- Short, punchy lines that read like a terminal log.
- Longer paragraphs that wrap comfortably without looking cramped.
Here’s a longer paragraph to test measure and rhythm. The goal is to avoid a “column inside a column” feeling, while still keeping the text legible. Reading mode should feel like a distraction-free page: no header chrome, no nav, just content. If this paragraph feels squeezed, the container is too narrow.
And here’s another paragraph with slightly different cadence. When you scroll, the header should stay out of the way, and the content should carry the page. If the background bleeds through or you can see underlying UI glow, the overlay isn’t truly opaque.
Code highlighting (small)
type CommandResult =
| { type: 'navigate'; to: string }
| { type: 'back' }
| { type: 'error'; message: string }
export function resolve(cmd: string): CommandResult {
const cleaned = cmd.trim()
if (!cleaned) return { type: 'error', message: 'empty command' }
if (cleaned === 'cd..') return { type: 'back' }
if (cleaned === './blog') return { type: 'navigate', to: '/blog' }
return { type: 'error', message: `unknown: ${cleaned}` }
}Code highlighting (large)
This block is intentionally big to test scroll performance and readability.
import { useEffect, useMemo, useRef, useState } from 'react'
type SearchHit = {
slug: string
title: string
summary: string
}
function normalize(input: string) {
return input.toLowerCase().trim().replace(/\s+/g, ' ')
}
function score(title: string, query: string) {
const t = normalize(title)
const q = normalize(query)
if (t === q) return 1000
if (t.startsWith(q)) return 800
const index = t.indexOf(q)
if (index !== -1) return 650 - Math.min(index, 200)
const tokens = q.split(' ').filter(Boolean)
if (!tokens.length) return -Infinity
for (const token of tokens) {
if (!t.includes(token)) return -Infinity
}
return 450 + tokens.length * 25
}
export function FakeFuzzyFinder({ hits, onPick }: { hits: SearchHit[]; onPick: (slug: string) => void }) {
const [query, setQuery] = useState('')
const inputRef = useRef<HTMLInputElement>(null)
useEffect(() => {
inputRef.current?.focus()
}, [])
const results = useMemo(() => {
if (!query.trim()) return hits.slice(0, 10)
return hits
.map((hit) => ({ hit, score: score(hit.title, query) }))
.filter((entry) => entry.score > 0)
.sort((a, b) => b.score - a.score)
.slice(0, 10)
.map((entry) => entry.hit)
}, [hits, query])
return (
<div className="space-y-3">
<input
ref={inputRef}
value={query}
onChange={(event) => setQuery(event.target.value)}
className="w-full rounded-md border px-3 py-2"
placeholder="type to filter"
/>
<ul className="space-y-2">
{results.map((hit) => (
<li key={hit.slug}>
<button type="button" onClick={() => onPick(hit.slug)}>
{hit.title}
</button>
</li>
))}
</ul>
</div>
)
}A table (for layout)
| Signal | What it means | Expected in reading mode |
|---|---|---|
| Background is solid | You can’t see the app behind | ✅ Yes |
| Full-window height | Content starts at viewport height | ✅ Yes |
| Scroll feels natural | Long content scrolls like a page | ✅ Yes |
| Exit is accessible | Escape + visible button works | ✅ Yes |
Long scrolling section
Below is a long list of short “log-like” lines to force a lot of vertical scrolling.
Checkpoints
- Checkpoint 001 — The CRT overlay shouldn’t leak through.
- Checkpoint 002 — The exit button should stay reachable.
- Checkpoint 003 — The text shouldn’t feel cramped.
- Checkpoint 004 — Code blocks should remain readable.
- Checkpoint 005 — The scroll should be smooth.
- Checkpoint 006 — Headings should break the flow nicely.
- Checkpoint 007 — Lists should have comfortable spacing.
- Checkpoint 008 — Links should keep the teal accent.
- Checkpoint 009 — Long words should wrap or overflow gracefully.
- Checkpoint 010 — The viewport should feel “owned” by the post.
More checkpoints (intentionally repetitive)
- Checkpoint 011 — Lorem ipsum but with purpose.
- Checkpoint 012 — The design should remain calm.
- Checkpoint 013 — The spacing should feel consistent.
- Checkpoint 014 — The page should not jiggle.
- Checkpoint 015 — Reading mode is about focus.
- Checkpoint 016 — Find should not open the browser’s search UI.
- Checkpoint 017 — Escape should always exit.
- Checkpoint 018 — The overlay should be truly opaque.
- Checkpoint 019 — The content should fill the width.
- Checkpoint 020 — This post keeps going.
A lot of paragraphs
Paragraph 01. Building UI is mostly about removing friction. Every extra decision the reader has to make costs attention.
Paragraph 02. A “reading mode” is an explicit choice: prioritize the content and let everything else disappear.
Paragraph 03. The goal is not maximal minimalism; it’s useful calm.
Paragraph 04. When a layout is too narrow, the reader feels boxed in. When it’s too wide, the eye gets lost. The “right” width depends on the font, line-height, and how the rest of the page frames the content.
Paragraph 05. In a terminal-themed site, you want strong contrast, crisp type, and just enough accent color to guide attention.
Paragraph 06. Code blocks are the hardest part of typography. They have different rhythm, different semantics, and usually require horizontal space.
Paragraph 07. Lists and headings are the easiest part, but they reveal inconsistencies in spacing quickly.
Paragraph 08. If reading mode is full-screen, it must also be full-height. It should feel like its own page.
Paragraph 09. The background must be solid — translucent layers read as “modal on top of an app,” not “reading.”
Paragraph 10. This is the tenth paragraph. There will be more.
Paragraph 11. Scrolling is a physical action. If the page stutters, it’s immediately noticeable.
Paragraph 12. Performance issues often show up only when the content is long.
Paragraph 13. Rehype/Shiki output for large code blocks is a great stress test.
Paragraph 14. The exit affordance should always be visible.
Paragraph 15. Keyboard shortcuts are a power-user feature, but they must be discoverable.
Paragraph 16. Cursor focus should not jump around unexpectedly.
Paragraph 17. Reading mode should not fight other shortcuts (like the command bar’s ⌘K).
Paragraph 18. This is still intentionally verbose.
Paragraph 19. Almost there.
Paragraph 20. Keep scrolling.
Even more content
Subsection A
- A1. A list item.
- A2. Another list item.
- A3. Yet another list item.
Subsection B
Here’s a blockquote to test spacing:
The best UI is the UI you don’t notice. The second best UI is the UI you can reason about.
Subsection C
And a final long-ish paragraph: if everything is working, this post should feel like it takes over the viewport in reading mode, scrolls like a real page, and exits instantly with Escape.
End
If you made it here, the scrolling test worked.