The Technical Section Got a Real Makeover
Redesigned the /technical page with a repo dashboard and gave the home page variable-density sections — four changes in one session.
Tag
21 posts in my garden · read my essays
Redesigned the /technical page with a repo dashboard and gave the home page variable-density sections — four changes in one session.
Updated the blog's content model to match the vault — five sections, new fields for time and location, technical card variant, and the garden as an umbrella concept.
Added full-text search to the blog — press Cmd+K and start typing to find anything across all posts.
The right-side table of contents on longer posts now highlights which section you're reading as you scroll.
Added a three-state dark mode toggle, plus proper error and 404 pages for when things go sideways.
My post template was rendering as a live article on the blog — fixed the filtering and cleaned out some leftover files.
Fixed HTML structure warnings on post cards and a mobile layout issue where the search box wasn't centering right.
A quirk in how Next.js handles URL objects was crashing every page locally during development. Eight lines changed, very annoying bug.
A big visual pass on the blog — portrait hero, card variants, leaf dividers, collapsible tag filter, and newsletter CTA with RSS fallback.
Removed a leftover library from the blog project after the feature it powered was deleted months ago.
Added RSS feeds for every section, a machine-readable posts index for AI tools, richer search metadata, and restyled link preview images.
Added a /tags page listing every topic on the blog, sorted by how many posts use each one.
Added a newsletter signup form (powered by Beehiiv) to the home page, post footer, and site footer — plus a whole new site footer.
Tags existed in every blog post since day one — I just never wired them up to actually appear on the page.
Four byte-identical duplicates left over from a rsync destination mistake, and the one-line Contentlayer slug regex that caused it.
Retiring the Twitter CTA in favor of a Substack email list, adding a 'meet my family' link to ocampo.io, and replacing the sidebar logo with a new SVG pointing to the personal site.
The inevitable follow-up to adding GTM: the browser's CSP was blocking the script, so this PR adds googletagmanager.com to script-src and img-src in next.config.js.
The one-character follow-up to PR #4: removing the stray colons from the CSP directive names so the browser stops ignoring the whole header.
First instrumentation on the blog: a gtag wrapper in lib/ga.js, a custom pages/_document.js with the Global Site Tag, and no npm dependency.
The shortest possible PR: collapsing a two-line JSX attribute into one. Shipping it anyway, because PRs are free and branch hygiene matters.
Universal Analytics is on the way out, so this PR migrates to GA4 via Google Tag Manager loaded through next/script, and renames everything from stevieismagic.com to steven.ocampo.io.