{"version":"https://jsonfeed.org/version/1.1","title":"BryceWray.com","description":"Bryce Wray’s website | Observations, opinions, geekiness","home_page_url":"https://www.brycewray.com/","feed_url":"https://www.brycewray.com/index.json","language":"en-us","authors":[{"name":"Bryce Wray","url":"https://www.brycewray.com/about/","avatar":"https://www.brycewray.com/images/icons/apple-icon-1024x1024.png"}],"items":[{"title":"MarkEdit: a TextEdit that knows Markdown","date_published":"2026-06-20T16:21:00-05:00","id":"https://www.brycewray.com/posts/2026/06/markedit-textedit-markdown/","url":"https://www.brycewray.com/posts/2026/06/markedit-textedit-markdown/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"Apple may never give us this answer to a long-standing itch; but, fortunately, someone else did.","content_html":"\u003cem\u003eApple may never give us this answer to a long-standing itch; but, fortunately, someone else did.\u003c/em\u003e\u003chr /\u003e\u003cp\u003eWe macOS users have long been familiar with using Apple\u0026rsquo;s included \u003ca href=\"https://support.apple.com/guide/textedit/welcome/mac\" rel=\"noopener\"\u003eTextEdit\u003c/a\u003e app for, as the name suggests, editing plain-text files. However, we macOS users who also like using \u003ca href=\"https://daringfireball.net/projects/markdown\" rel=\"noopener\"\u003eMarkdown\u003c/a\u003e have found TextEdit lacking \u0026mdash; it can open and edit such files, of course, but it can\u0026rsquo;t do Markdown-ish things in them \u0026mdash; and wished Apple would make it Markdown-savvy. While there\u0026rsquo;s no indication Apple ever intends to do that, the good news is that there now is a FOSS app, \u003ca href=\"https://github.com/MarkEdit-app/MarkEdit\" rel=\"noopener\"\u003eMarkEdit\u003c/a\u003e, which is essentially TextEdit that speaks Markdown. And that may well be good enough.\u003c/p\u003e\n\u003cp\u003eThe vast majority of my Markdown-editing endeavors over the last few years, especially for this website, have been spent in \u003ca href=\"https://ia.net/writer\" rel=\"noopener\"\u003eiA Writer\u003c/a\u003e, and I suspect that will continue to be the case long-term.\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e That said, I wrote this post mostly in MarkEdit, and found the experience to be a good one.\u003c/p\u003e\n\u003cdiv class=\"relative big-img-div rounded-bkgd imgB-657955f6184dac7b4a8dc2abe3b8d2f5-GIP\" data-pagefind-ignore\u003e\n\t\t\t\u003cpicture data-pagefind-ignore\u003e\n\t\t\t\t\u003csource type=\"image/webp\" srcset=\"/posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_82e8f92723e9c0b6.webp 320w, /posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_5dc605200c088682.webp 640w, /posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_3b10bd0c30570c46.webp 960w, /posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_388ca8cda7a76584.webp 1280w, /posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_229f5e60f725a0a.webp 1600w, /posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_2110a3c1b65e4038.webp 1920w\" sizes=\"auto, (min-width: 1024px) 100vw, 50vw\" /\u003e\n\t\t\t\t\u003csource type=\"image/jpeg\" srcset=\"/posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_54c5a89aedb77ca0.jpg 320w, /posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_9c4703f239da57f8.jpg 640w, /posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_98a1096af0edd328.jpg 960w, /posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_e58aa287b8623b35.jpg 1280w, /posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_c6d3682de1d27580.jpg 1600w, /posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_cc8f76c5c90ec62d.jpg 1920w\" sizes=\"auto, (min-width: 1024px) 100vw, 50vw\" /\u003e\n\t\t\t\t\u003cimg class=\"h-auto w-full animate-fade shadow\" src=\"/posts/2026/06/markedit-textedit-markdown/MarkEdit_screenshot_1920x1270_hu_9c4703f239da57f8.jpg\" width=\"1920\" height=\"1270\" alt=\"Screen capture of MarkEdit application on macOS\" title=\"Screen capture of MarkEdit application on macOS\" loading=\"lazy\" data-pagefind-ignore /\u003e\n\t\t\t\u003c/picture\u003e\u003c/div\u003e\n\n\u003cp\u003eOther than its ability to be \u0026ldquo;Markdown-savvy TextEdit,\u0026rdquo; another of MarkEdit\u0026rsquo;s key advantages is that it\u0026rsquo;s a native macOS app. To put that another way, it doesn\u0026rsquo;t rely on \u003ca href=\"https://www.electronjs.org/\" rel=\"noopener\"\u003eElectron\u003c/a\u003e or any other bloated framework. This keeps it small (four MB as installed), light, and quick, even on older Macs \u0026mdash; although it\u0026rsquo;s mainly for newer ones, albeit with special, additional versions for macOS iterations from several years ago. MarkEdit also works, looks, and feels like a \u003cem\u003ereal\u003c/em\u003e macOS app. As its GitHub page explains:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eUI controls remain native to macOS in both aesthetics and behavior, including force-touch word lookup, inline predictions, and Writing Tools.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003cdel\u003eOh, and for those like me who care about such things: it appears MarkEdit is \u003cem\u003enot\u003c/em\u003e (yet?) vibe-coded. How long that will continue to be the case, I obviously can\u0026rsquo;t know; but, for now, MarkEdit seems to be a human(s)-built endeavor.\u003c/del\u003e\u003c/p\u003e\n\u003cp class=\"box\"\u003e\u003cstrong\u003eCorrection\u003c/strong\u003e: I looked again at MarkEdit\u0026rsquo;s GitHub repo and saw that multiple LLMs are in the \u003ca href=\"https://github.com/MarkEdit-app/MarkEdit/graphs/contributors\" rel=\"noopener\"\u003elist of contributors\u003c/a\u003e. \u003cem\u003e[Sigh.]\u003c/em\u003e My apologies for the mistaken and now stricken-through assumption above.\u003c/p\u003e\n\u003cp\u003eIncidentally: to date, although the original TextEdit is on iOS/iPadOS as well as macOS, MarkEdit is macOS-only.\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003eOne other (and unrelated) item while I have your much-appreciated attention . . .\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;ve spoken here a number of times about how I converted my old Intel iMac to Linux. \u003ca href=\"/posts/2026/03/mixed-nuts-17/\"\u003eMost recently\u003c/a\u003e, my Linux distribution of choice was the \u003ca href=\"https://archlinux.org\" rel=\"noopener\"\u003eArch\u003c/a\u003e-based \u003ca href=\"https://cachyos.org\" rel=\"noopener\"\u003eCachyOS\u003c/a\u003e, after I\u0026rsquo;d spent over two years with \u003ca href=\"https://fedoraproject.org\" rel=\"noopener\"\u003eFedora\u003c/a\u003e. But, while I still think CachyOS itself is pretty interesting, I\u0026rsquo;ve now reversed course and gone back to Fedora because of the \u003ca href=\"https://www.securityweek.com/atomic-arch-supply-chain-attack-hits-1500-aur-packages/\" rel=\"noopener\"\u003ecraziness\u003c/a\u003e \u0026mdash; still ongoing as of this writing \u0026mdash; that we\u0026rsquo;ve seen in the \u003ca href=\"https://aur.archlinux.org\" rel=\"noopener\"\u003eArch Users Repository (AUR)\u003c/a\u003e over the last few weeks. Yes, I knew and observed the correct procedures for safely using the AUR; and, besides, I really wasn\u0026rsquo;t using the AUR all that much anyway (just two packages, one of which is \u003ca href=\"https://support.1password.com/install-linux/#arch-linux\" rel=\"noopener\"\u003eprovided by no less than 1Password\u003c/a\u003e); but I simply felt better and safer in going back to Fedora. At my age, I\u0026rsquo;ll gladly pass up a little performance for greater peace of mind.\u003c/p\u003e\n\u003cdiv class=\"footnotes\" role=\"doc-endnotes\"\u003e\n\u003chr\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003eIncidentally, as I write, iA Writer has just reached \u003ca href=\"https://ia.net/topics/search-to-navigate\" rel=\"noopener\"\u003ev.8.0\u003c/a\u003e. To my surprise, I received the upgrade for free even though it\u0026rsquo;s been \u003cem\u003eover seven years\u003c/em\u003e since I bought the macOS version of iA Writer as v.5-something-or-other.\u0026#160;\u003ca href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“MarkEdit: a TextEdit that knows Markdown”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"},{"title":"Mixed nuts #18","date_published":"2026-06-03T14:27:00-05:00","id":"https://www.brycewray.com/posts/2026/06/mixed-nuts-18/","url":"https://www.brycewray.com/posts/2026/06/mixed-nuts-18/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"AVIF support in Hugo, hashes in action(s), floaters, and clankers.","content_html":"\u003cem\u003eAVIF support in Hugo, hashes in action(s), floaters, and clankers.\u003c/em\u003e\u003chr /\u003e\u003cp\u003eFor no major reason other than that I feel like writing about a few odds and ends which have recently occupied my mind, here\u0026rsquo;s \u003ca href=\"/posts/2026/03/mixed-nuts-17/\"\u003eyet another\u003c/a\u003e \u0026ldquo;Mixed nuts\u0026rdquo; post.\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003eAlthough I haven\u0026rsquo;t yet tried it on this here site, the \u003ca href=\"https://gohugo.io\" rel=\"noopener\"\u003eHugo\u003c/a\u003e static site generator has added \u003ca href=\"https://aomediacodec.github.io/av1-avif/\" rel=\"noopener\"\u003eAVIF\u003c/a\u003e support to its already impressive \u003ca href=\"https://gohugo.io/content-management/image-processing/\" rel=\"noopener\"\u003eimage processing capabilities\u003c/a\u003e as of \u003ca href=\"https://github.com/gohugoio/hugo/releases/tag/v0.162.0\" rel=\"noopener\"\u003ev.0.162.0\u003c/a\u003e. The curious may want to check out \u003ca href=\"https://github.com/bep/hdrsdr.com\" rel=\"noopener\"\u003ethis demo repo\u003c/a\u003e and its \u003ca href=\"https://hdrsdr.com/\" rel=\"noopener\"\u003ecorresponding site\u003c/a\u003e. Note that, apparently, \u003ca href=\"https://discourse.gohugo.io/t/hugo-v0-162-0-released/57207/14\" rel=\"noopener\"\u003enot all browsers\u003c/a\u003e handle the \u003ca href=\"https://www.digitaltrends.com/photography/what-is-hdr-photography/\" rel=\"noopener\"\u003eHDR\u003c/a\u003e aspects equally well.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eWhen I build this site through CI/CD, I typically use a \u003ca href=\"https://github.com/features/actions\" rel=\"noopener\"\u003eGitHub Action\u003c/a\u003e which, in turn, calls on \u003cstrong\u003eother\u003c/strong\u003e actions to facilitate things \u0026mdash;\u003c/em\u003e e.g.\u003cem\u003e, \u003ca href=\"https://github.com/actions/checkout\" rel=\"noopener\"\u003e\u003ccode\u003echeckout\u003c/code\u003e\u003c/a\u003e for accessing the site repo\u0026rsquo;s contents. After reading about one supply-chain attack after another over the last few months, I finally decided to heed widely discussed advice and \u003cstrong\u003epin\u003c/strong\u003e those actions by their respective commit-hashes, \u003cstrong\u003enot\u003c/strong\u003e their release tags. This means that even if a bad actor manages to hijack the repo of (again,\u003c/em\u003e e.g.\u003cem\u003e) \u003ccode\u003echeckout\u003c/code\u003e, my overarching GHA won\u0026rsquo;t be affected. \u003ca href=\"https://blog.rafaelgss.dev/why-you-should-pin-actions-by-commit-hash\" rel=\"noopener\"\u003eThis article\u003c/a\u003e by Rafael Gonzaga explains; and \u003ca href=\"https://www.stepsecurity.io/blog/pinning-github-actions-for-enhanced-security-a-complete-guide\" rel=\"noopener\"\u003ethis one\u003c/a\u003e on the StepSecurity website gives you additional details, notably how you \u003cstrong\u003eget\u003c/strong\u003e each hash in the first place.\u003c/em\u003e\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e\u003c/p\u003e\n\u003cp\u003eAh, me, but getting old does so bite sometimes. To quote T. S. Eliot\u0026rsquo;s \u003ca href=\"https://poets.org/poem/love-song-j-alfred-prufrock\" rel=\"noopener\"\u003e\u003cem\u003eThe Love Song of J. Alfred Prufrock\u003c/em\u003e\u003c/a\u003e:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eI grow old . . . I grow old . . .\u003cbr\u003e\nI shall wear the bottoms of my trousers rolled.\u003c/p\u003e\n\u003cp\u003eShall I part my hair behind? Do I dare to eat a peach?\u003cbr\u003e\nI shall wear white flannel trousers, and walk upon the beach.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eWell, that\u0026rsquo;s all well and good, but Eliot never said a word about \u003ca href=\"https://newsnetwork.mayoclinic.org/discussion/mayo-clinic-q-and-a-most-eye-floaters-caused-by-age-related-changes/\" rel=\"noopener\"\u003e\u003cem\u003efloaters\u003c/em\u003e\u003c/a\u003e; and, boy, are they ever in my eyes (which are both aged and myopic\u003csup id=\"fnref:2\"\u003e\u003ca href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e2\u003c/a\u003e\u003c/sup\u003e, an especially floaters-friendly combo). So much so, in fact, that my web-browsing habits have veered away from a position I took here six years ago \u0026mdash; \u003ca href=\"/posts/2020/05/mixed-nuts-2020-05/\"\u003ein one of the earliest \u0026ldquo;Mixed nuts\u0026rdquo; posts\u003c/a\u003e, as a matter of fact \u0026mdash; on the question of light mode \u003cem\u003evs.\u003c/em\u003e dark mode. Despite \u003ca href=\"https://tidbits.com/2019/05/31/the-dark-side-of-dark-mode/\" rel=\"noopener\"\u003estudies\u003c/a\u003e I cited back then, I am now making use of dark mode whenever possible because, simply put, the floaters make reading light text on dark backgrounds far less aggravating than is the case with dark text on light backgrounds. I will reserve judgment on the trousers, the hair (as if I had enough to consider), the peach, and the beach.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eI\u0026rsquo;ve added another \u0026ldquo;\u003ca href=\"/posts/2024/06/slash-pages-existing-new/\"\u003eslash page\u003c/a\u003e.\u0026rdquo; This one explains my \u003ca href=\"/ai/\"\u003estances on AI where the site is concerned\u003c/a\u003e. The bottom line: I don\u0026rsquo;t use AI for writing, although I do let it give me \u003cstrong\u003elimited\u003c/strong\u003e assistance in coding. The day when I can no longer write without the help of clankers will be the day when I \u003cstrong\u003ecall\u003c/strong\u003e it a day, website-wise. There\u0026rsquo;s already enough slop out there without this site\u0026rsquo;s adding to it.\u003c/em\u003e\u003c/p\u003e\n\u003cdiv class=\"footnotes\" role=\"doc-endnotes\"\u003e\n\u003chr\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003eIn short: you navigate to the web page of the commit itself and copy the hash from the end of the page\u0026rsquo;s URL.\u0026#160;\u003ca href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli id=\"fn:2\"\u003e\n\u003cp\u003e\u003cstrong\u003eSort-of correction\u003c/strong\u003e: Actually, on second thought, it\u0026rsquo;s not accurate to say that I have myopia now, because I had cataract surgeries nearly ten years ago which fixed that. However, I suspect that my having \u003cem\u003ehad\u003c/em\u003e myopia (and severe myopia, at that) for a bit over sixty years prior to those procedures may still be contributing to my floaters-related woes.\u0026#160;\u003ca href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“Mixed nuts #18”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"},{"title":"A “new normal” update","date_published":"2026-05-04T15:29:00-05:00","id":"https://www.brycewray.com/posts/2026/05/new-normal-update/","url":"https://www.brycewray.com/posts/2026/05/new-normal-update/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"Improving my scripting following hvm’s recent changes.","content_html":"\u003cem\u003eImproving my scripting following hvm’s recent changes.\u003c/em\u003e\u003chr /\u003e\u003cp\u003e\u003ca href=\"/posts/2025/12/new-normal-starting-hugo-0.153.x/\"\u003eLate last year\u003c/a\u003e, I had to adapt this website\u0026rsquo;s repository to accommodate a change in how \u003ca href=\"https://gohugo.io\" rel=\"noopener\"\u003eHugo\u003c/a\u003e\u0026rsquo;s macOS version is packaged. In short, I started to use the \u003ca href=\"https://github.com/jmooring/hvm/\" rel=\"noopener\"\u003ehvm (Hugo Version Manager) app\u003c/a\u003e to manage my computer\u0026rsquo;s use of the Hugo binary. More recently, after a change to hvm itself, I made a further adaptation. Fortunately for me, as in the case of that earlier post, Hugo maintainer and hvm creator \u003ca href=\"https://github.com/jmooring\" rel=\"noopener\"\u003eJoe Mooring\u003c/a\u003e gave me help in overcoming, as I described to him, \u0026ldquo;my embarrassing lack of \u003ca href=\"https://english.stackexchange.com/questions/47694/when-did-things-like-fu-start-to-spread\" rel=\"noopener\"\u003escripting-fu\u003c/a\u003e.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eI will assume you\u0026rsquo;ve already read the \u003ca href=\"/posts/2025/12/new-normal-starting-hugo-0.153.x/\"\u003eaforementioned post from last December\u003c/a\u003e; that way, I needn\u0026rsquo;t go into a huge amount of detail about why I switched to hvm, how it works, and so on. Instead, this post is about the latest incarnation of hvm, how \u003cem\u003eit\u003c/em\u003e works, and what that meant \u0026mdash; and, to be fair, made possible \u0026mdash; for my purposes.\u003c/p\u003e\n\u003cp\u003eWhen I first began using hvm, it was at \u003ca href=\"https://github.com/jmooring/hvm/releases/tag/v0.9.0\" rel=\"noopener\"\u003ev.0.9.0\u003c/a\u003e. At that point, and for a few versions thereafter, it was providing only one \u003ca href=\"https://gohugo.io/installation/linux/\" rel=\"noopener\"\u003eedition\u003c/a\u003e of Hugo, the extended one. As a result, hvm\u0026rsquo;s auto-generated \u003ccode\u003e.hvm\u003c/code\u003e file needed to give you only the Hugo version number being used by your repo, such as:\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-plaintext\" data-lang=\"plaintext\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ev0.153.0\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eThen, a few weeks ago, Mooring released \u003ca href=\"https://github.com/jmooring/hvm/releases/tag/v0.14.0\" rel=\"noopener\"\u003ehvm v.0.14.0\u003c/a\u003e, the first version which allowed the user to choose from among multiple different Hugo editions. Currently, those are standard, standard-with-deploy, extended, and extended-with-deploy.\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e This change in hvm, thus, would require the resulting \u003ccode\u003e.hvm\u003c/code\u003e file to provide more information. For example, as I write, here is the content of my repo\u0026rsquo;s \u003ccode\u003e.hvm\u003c/code\u003e file:\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-plaintext\" data-lang=\"plaintext\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ev0.161.1/standard\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eI initially thought this change would bollix up the local scripting I described in that previous post, but it didn\u0026rsquo;t \u003cem\u003ebecause\u003c/em\u003e hvm 0.14.0+ installs the user-specified Hugo binary in a directory structure that corresponds exactly to the mini-path in that \u003ccode\u003e.hvm\u003c/code\u003e file. In other words, this:\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-plaintext\" data-lang=\"plaintext\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e/Users/$USERNAME/Library/Caches/hvm/$HUGO_VERSION/hugo\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003e. . . still works the same, because \u003ccode\u003e$HUGO_VERSION\u003c/code\u003e \u003cem\u003econtinues to be\u003c/em\u003e the same as what\u0026rsquo;s in \u003ccode\u003e.hvm\u003c/code\u003e:\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-plaintext\" data-lang=\"plaintext\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e/Users/$USERNAME/Library/Caches/hvm/v0.161.1/standard/hugo\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eI got an additional benefit from hvm 0.14.0+, thanks to Mooring\u0026rsquo;s \u003ca href=\"https://github.com/jmooring/hvm/issues/218#issuecomment-4180516808\" rel=\"noopener\"\u003ehelpful suggestion\u003c/a\u003e: it now makes my site-deployment CI/CD a little less needful of my attention. (After all, automation is supposed to be \u003cem\u003eless\u003c/em\u003e troublesome, not \u003cem\u003emore\u003c/em\u003e so, than doing everything manually.) He showed me, in \u003ca href=\"https://github.com/jmooring/hosting-github-pages-hvm/blob/main/.github/workflows/hugo.yaml#L54-L74\" rel=\"noopener\"\u003epart of a demo repo he maintains\u003c/a\u003e, how he uses the \u003ccode\u003e.hvm\u003c/code\u003e output to tell a \u003ca href=\"https://docs.github.com/en/actions/get-started/understand-github-actions\" rel=\"noopener\"\u003eGitHub Action\u003c/a\u003e which version of Hugo it should download. Previously, I\u0026rsquo;d always provided that information through manually updating my GitHub Actions workflow file whenever I updated Hugo. Now, with a slight variation\u003csup id=\"fnref:2\"\u003e\u003ca href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e2\u003c/a\u003e\u003c/sup\u003e on Mooring\u0026rsquo;s code, the workflow file gets that info from \u003ccode\u003e.hvm\u003c/code\u003e:\u003c/p\u003e\n\n\t\u003cdiv class=\"highlight-wide\"\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e- \u003cspan class=\"nt\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eHugo download/install\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"nt\"\u003erun\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"sd\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e    if [ -f .hvm ]; then\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e      hvm_raw=$(cat .hvm)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e      HUGO_VERSION=$(echo \u0026#34;${hvm_raw%/*}\u0026#34; | tr -d \u0026#39;v\u0026#39;)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e    fi\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e    wget https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_linux-amd64.deb -O hugo_${HUGO_VERSION}_linux-amd64.deb\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e    sudo dpkg -i hugo*.deb\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eIn the third line of that \u003ccode\u003eif\u003c/code\u003e/\u003ccode\u003efi\u003c/code\u003e loop, \u003ccode\u003e${hvm_raw%/*}\u003c/code\u003e reads the \u003ccode\u003e.hvm\u003c/code\u003e file\u0026rsquo;s contents \u003ca href=\"https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html\" rel=\"noopener\"\u003eup to the slash\u003c/a\u003e, while \u003ca href=\"https://linuxize.com/post/linux-tr-command/\" rel=\"noopener\"\u003e\u003ccode\u003etr -d 'v'\u003c/code\u003e\u003c/a\u003e removes the \u003ccode\u003ev\u003c/code\u003e that precedes the version number (since that \u003ccode\u003ev\u003c/code\u003e isn\u0026rsquo;t used in the actual file names for the \u003ca href=\"https://github.com/gohugoio/hugo/releases/\" rel=\"noopener\"\u003eHugo release\u003c/a\u003e assets). The result provides \u003cstrong\u003eonly\u003c/strong\u003e the Hugo version number as \u003ccode\u003eHUGO_VERSION\u003c/code\u003e, which the succeeding lines use to download the desired version of Hugo onto the GitHub Actions runner.\u003c/p\u003e\n\u003cp\u003eIncidentally, if you prefer a \u003ca href=\"https://docs.gitlab.com/ci/\" rel=\"noopener\"\u003eGitLab CI/CD\u003c/a\u003e version of this, here\u0026rsquo;s one I\u0026rsquo;ve used:\u003c/p\u003e\n\n\t\u003cdiv class=\"highlight-wide\"\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e- \u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"sd\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e  if [ -f .hvm ]; then\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e    hvm_raw=$(cat .hvm)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e    HUGO_VERSION=$(echo \u0026#34;${hvm_raw%/*}\u0026#34; | tr -d \u0026#39;v\u0026#39;)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e  fi\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e- \u003cspan class=\"l\"\u003eecho \u0026#34;Downloading and installing Hugo v.$HUGO_VERSION ...\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e- \u003cspan class=\"l\"\u003ecurl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_linux-amd64.deb\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e- \u003cspan class=\"l\"\u003eapt install -y ./hugo_${HUGO_VERSION}_linux-amd64.deb\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eOf course, given how the various CI/CD platforms \u003ca href=\"https://daringfireball.net/linked/2026/05/04/commits-on-github-are-up-14x-year-over-year\" rel=\"noopener\"\u003eseem increasingly overwhelmed by AI-created traffic\u003c/a\u003e, I may end up reverting to \u003ca href=\"/posts/2023/10/direct-deployments-quicker-slicker/\"\u003emy previously used direct deployment method\u003c/a\u003e \u0026mdash; in which case, I wouldn\u0026rsquo;t have to inform \u003cem\u003eany\u003c/em\u003e remote code runner of the Hugo version I\u0026rsquo;m using. However, while I\u0026rsquo;m still using remotely hosted CI/CD, I\u0026rsquo;m pleased to use these methods to simplify things just a tad.\u003c/p\u003e\n\u003cp class=\"box\"\u003e\u003cstrong\u003eUpdate, 2026-05-05\u003c/strong\u003e: On a slightly related note, I learned while researching for this post that, at long last, GitHub Actions now allows you to set your runner\u0026rsquo;s time zone (\u003ca href=\"https://github.com/MathRobin/timezone-action\" rel=\"noopener\"\u003eincluding for cron jobs\u003c/a\u003e) by simply \u003ca href=\"https://github.com/MathRobin/timezone-action/issues/4#issuecomment-4202168541\" rel=\"noopener\"\u003eusing a \u003ccode\u003eTZ\u003c/code\u003e variable\u003c/a\u003e, as has long been possible in GitLab CI/CD. This eliminates the need to access other, mostly (apparently) unmaintained Actions to perform that one basic function within one\u0026rsquo;s workflow file.\u003c/p\u003e\n\u003cdiv class=\"footnotes\" role=\"doc-endnotes\"\u003e\n\u003chr\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003eHugo\u0026rsquo;s extended edition (and, presumably, its extended-with-deploy edition) will be deprecated \u003ca href=\"https://github.com/jmooring/hvm/issues/218#issue-4165637816\" rel=\"noopener\"\u003esometime within the next year or so\u003c/a\u003e. With the \u003ca href=\"https://github.com/gohugoio/hugo/releases/tag/v0.153.0\" rel=\"noopener\"\u003erecent deprecation of its embedded LibSass\u003c/a\u003e (which itself is \u003ca href=\"https://sass-lang.com/blog/libsass-is-deprecated/\" rel=\"noopener\"\u003elong since gone\u003c/a\u003e), the extended edition\u0026rsquo;s only remaining \u003cem\u003eraison d\u0026rsquo;être\u003c/em\u003e has ended, so removing that edition from the list of regular releases will ease the Hugo team\u0026rsquo;s maintenance burdens.\u0026#160;\u003ca href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli id=\"fn:2\"\u003e\n\u003cp\u003eI now always use the standard edition of Hugo, so I didn\u0026rsquo;t need an additional line from Mooring\u0026rsquo;s code that also pulled the Hugo edition. Instead, my script simply gets the standard edition of whatever Hugo version is mentioned in \u003ccode\u003e.hvm\u003c/code\u003e.\u0026#160;\u003ca href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“A “new normal” update”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"},{"title":"Hugo’s new CSS powers","date_published":"2026-04-02T12:19:00-05:00","id":"https://www.brycewray.com/posts/2026/04/hugos-new-css-powers/","url":"https://www.brycewray.com/posts/2026/04/hugos-new-css-powers/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"A recent update can make it easier than ever to style your site, depending on how you want to do that styling.","content_html":"\u003cem\u003eA recent update can make it easier than ever to style your site, depending on how you want to do that styling.\u003c/em\u003e\u003chr /\u003e\u003cp\u003eAs I mentioned in my \u003ca href=\"/posts/2026/03/mixed-nuts-17/\"\u003eprevious post\u003c/a\u003e, I was intrigued when the release of \u003ca href=\"https://gohugo.io\" rel=\"noopener\"\u003eHugo\u003c/a\u003e \u003ca href=\"https://github.com/gohugoio/hugo/releases/tag/v0.158.0\" rel=\"noopener\"\u003ev.0.158.0\u003c/a\u003e introduced its \u003ca href=\"https://gohugo.io/functions/css/build/#article\" rel=\"noopener\"\u003e\u003ccode\u003ecss.Build\u003c/code\u003e\u003c/a\u003e function. The new powers that resulted are worth a look when you consider all the aspects of styling a site you\u0026rsquo;ve built, or plan to build, on Hugo. Still, the enhancements have certain limitations of which you\u0026rsquo;ll also want to be aware.\u003c/p\u003e\n\u003cp\u003eWhen forming the styling structure for a Hugo-based website, you have a variety of options. CSS itself has gained many additional features over the years, and browsers have improved to handle them.\u003c/p\u003e\n\u003cp\u003eFor example, it wasn\u0026rsquo;t so long ago that simply nesting your CSS like this . . .\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003emy-div\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"k\"\u003ebackground-color\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#ffffaa\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"err\"\u003eh1\u003c/span\u003e \u003cspan class=\"err\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"k\"\u003efont-size\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"kt\"\u003erem\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#005500\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"nt\"\u003ep\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"k\"\u003efont-size\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mf\"\u003e0.75\u003c/span\u003e\u003cspan class=\"kt\"\u003erem\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e}\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003e. . . required \u003ca href=\"https://developer.mozilla.org/en-US/docs/Glossary/CSS_preprocessor\" rel=\"noopener\"\u003epre-processing\u003c/a\u003e through \u003ca href=\"https://sass-lang.com\" rel=\"noopener\"\u003eSass\u003c/a\u003e or \u003ca href=\"https://www.cssmine.com/ebook/postprocessing\" rel=\"noopener\"\u003epost-processing\u003c/a\u003e through something like \u003ca href=\"https://postcss.org\" rel=\"noopener\"\u003ePostCSS\u003c/a\u003e or \u003ca href=\"https://lightningcss.com\" rel=\"noopener\"\u003eLightning CSS\u003c/a\u003e; but, now, you can deliver CSS in production just like you see above, and any browser compatible with \u003ca href=\"https://web.dev/baseline/2023\" rel=\"noopener\"\u003eBaseline 2023\u003c/a\u003e will display it as you intend. \u003cstrong\u003eHowever\u003c/strong\u003e, unless you\u0026rsquo;re sure everyone in your site\u0026rsquo;s target audience is using a sufficiently updated browser, you have to adapt your site\u0026rsquo;s production styling accordingly \u0026mdash; manually by using only pre-2023 vanilla CSS, or automatically through Sass-processed CSS or using a post-processor to \u003ca href=\"https://crystallize.com/answers/tech-dev/compiling-vs-transpiling\" rel=\"noopener\"\u003e\u003cem\u003etranspile\u003c/em\u003e\u003c/a\u003e modern CSS for compatibility with older browsers. That post-processing is one way that \u003ccode\u003ecss.Build\u003c/code\u003e shines (mostly; more on that in a little while).\u003c/p\u003e\n\u003cp\u003eUnless your site\u0026rsquo;s styling is very simple, you may want to \u003ca href=\"https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Organizing#break_large_stylesheets_into_multiple_smaller_ones\" rel=\"noopener\"\u003eorganize your CSS into multiple files\u003c/a\u003e. If so, you then must determine how best to deliver all that CSS in production. Of course, your HTML can just link to multiple stylesheets, but it\u0026rsquo;s often better to combine multiple CSS files, especially for \u003ca href=\"https://www.smashingmagazine.com/2015/08/understanding-critical-css/#what-is-critical-css\" rel=\"noopener\"\u003ecritical CSS\u003c/a\u003e, into one production-side \u003cem\u003ebundle\u003c/em\u003e. That, too, formerly required one or more external packages, but CSS-bundling is another advantage \u003ccode\u003ecss.Build\u003c/code\u003e can give you.\u003c/p\u003e\n\u003cp\u003eAlso, you almost certainly want to \u003cem\u003eminify\u003c/em\u003e your CSS for production. Although Hugo\u0026rsquo;s long been able to do that for CSS, as it \u003ca href=\"https://gohugo.io/functions/resources/minify/\" rel=\"noopener\"\u003edoes for other delivered files\u003c/a\u003e, \u003ccode\u003ecss.Build\u003c/code\u003e now provides another way to do it for just CSS.\u003c/p\u003e\n\u003cp\u003eAll that said, \u003ccode\u003ecss.Build\u003c/code\u003e has some gotchas which you\u0026rsquo;ll need to take into account when assessing whether this feature can be your sole \u0026ldquo;helper\u0026rdquo; where CSS is concerned rather than having to use, say, Sass in development and/or PostCSS on the production side.\u003c/p\u003e\n\u003cp\u003eWhat it comes down to is that you must make a judgment call about which newer-style CSS features your site may require. Since \u003ccode\u003ecss.Build\u003c/code\u003e works atop the \u003ca href=\"https://github.com/evanw/esbuild\" rel=\"noopener\"\u003eesbuild package\u003c/a\u003e, the best source for what \u003ccode\u003ecss.Build\u003c/code\u003e can and can\u0026rsquo;t do in this regard is the actual \u003ca href=\"https://esbuild.github.io/content-types/#css\" rel=\"noopener\"\u003eCSS-specific documentation\u003c/a\u003e for esbuild itself; this information lists the features for which esbuild performs either transpilation or \u003ca href=\"https://developer.mozilla.org/en-US/docs/Glossary/Vendor_Prefix\" rel=\"noopener\"\u003ebrowser-prefixing\u003c/a\u003e. And, even when armed with this knowledge, you still must \u003cstrong\u003etest\u003c/strong\u003e how/whether \u003ccode\u003ecss.Build\u003c/code\u003e converts all the newer-style CSS you wish to deploy.\u003c/p\u003e\n\u003cp\u003eFor those items which esbuild (and, thus, \u003ccode\u003ecss.Build\u003c/code\u003e) currently can\u0026rsquo;t convert to your liking, you\u0026rsquo;re left with two choices: (a.) add some post-processing that will fill in the gaps; or (b.) decide to target only those browser versions that \u0026ldquo;know\u0026rdquo; those CSS items. While deciding, you\u0026rsquo;ll appreciate the convenience of tools like the \u003ca href=\"https://browsersl.ist/\" rel=\"noopener\"\u003eBrowserslist playground\u003c/a\u003e and the \u003ca href=\"https://web.dev/baseline/\" rel=\"noopener\"\u003eBaseline\u003c/a\u003e-specific \u003ca href=\"https://web-platform-dx.github.io/web-features/supported-browsers/\" rel=\"noopener\"\u003elist of supported browsers\u003c/a\u003e.\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e\u003c/p\u003e\n\u003c!--https://discourse.gohugo.io/t/hugo-v0-158-0-released/56868/6--\u003e\n\u003cp\u003eSuch limitations notwithstanding, \u003ccode\u003ecss.Build\u003c/code\u003e\u0026rsquo;s other capabilities that I mentioned above can reduce or eliminate your needs for other CSS processors. Bundling and minification work right out of the box. And, best of all, \u003ccode\u003ecss.Build\u003c/code\u003e works \u003cem\u003every\u003c/em\u003e quickly, which is an especially big advantage during development. The bigger your site and the more CSS you\u0026rsquo;re using, the more you\u0026rsquo;ll appreciate the speed of \u003ccode\u003ecss.Build\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003ePerhaps, after thinking through all this, you decide \u003ccode\u003ecss.Build\u003c/code\u003e might just work for your site. Other than those specific CSS gotchas we already mentioned above, what else, if anything, would you lose by going with just a vanilla-CSS-and-\u003ccode\u003ecss.Build\u003c/code\u003e solution? To help answer that, let\u0026rsquo;s conclude by looking at the alternatives as you would use them in Hugo:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eSass pre-processing\u003c/strong\u003e (involves writing \u003ccode\u003e.scss\u003c/code\u003e or \u003ccode\u003e.sass\u003c/code\u003e files, rather than \u003ccode\u003e.css\u003c/code\u003e files)\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRequires \u003ca href=\"https://gohugo.io/functions/css/sass/#dart-sass\" rel=\"noopener\"\u003euse of the Dart Sass binary\u003c/a\u003e (\u003cstrong\u003ebut\u003c/strong\u003e works smoothly and very quickly with \u003ca href=\"https://gohugo.io/hugo-pipes/\" rel=\"noopener\"\u003eHugo Pipes\u003c/a\u003e).\u003c/li\u003e\n\u003cli\u003eProvides no browser-prefixing. Remember, it\u0026rsquo;s a \u003cstrong\u003epre\u003c/strong\u003e-processor. For that, you need to use Sass \u003cstrong\u003eand\u003c/strong\u003e a post-processor, which adds more complexity and likely slows down your work, especially in development.\u003c/li\u003e\n\u003cli\u003eLets you nest your styling , but \u003ca href=\"https://sass-lang.com/blog/sass-and-native-nesting/\" rel=\"noopener\"\u003ecurrently\u003c/a\u003e doesn\u0026rsquo;t support native CSS nesting \u0026mdash; which may not matter to you if your styling code is all-Sass anyway.\u003c/li\u003e\n\u003cli\u003eProvides bundling through Sass\u0026rsquo;s \u003ca href=\"https://sass-lang.com/documentation/at-rules/use/\" rel=\"noopener\"\u003e\u003ccode\u003e@use\u003c/code\u003e\u003c/a\u003e command.\u003c/li\u003e\n\u003cli\u003ePerforms minification through the \u003ca href=\"https://gohugo.io/functions/css/sass/#outputstyle\" rel=\"noopener\"\u003e\u0026ldquo;compressed\u0026rdquo; \u003ccode\u003eoutputStyle\u003c/code\u003e option\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003eOffers \u003ca href=\"https://sass-lang.com/documentation/modules/math/\" rel=\"noopener\"\u003emath functions\u003c/a\u003e, \u003ca href=\"https://sass-lang.com/documentation/syntax/special-functions/#if\" rel=\"noopener\"\u003elogical functions\u003c/a\u003e, and \u003ca href=\"https://sass-lang.com/documentation/at-rules/mixin/\" rel=\"noopener\"\u003emixins\u003c/a\u003e \u0026mdash; some or all of which either \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Values_and_units/Using_math_functions#advanced_css_math_functions\" rel=\"noopener\"\u003ealready are\u003c/a\u003e, or \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/if\" rel=\"noopener\"\u003emight\u003c/a\u003e \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Custom_functions_and_mixins\" rel=\"noopener\"\u003ebecome\u003c/a\u003e, part of Baseline CSS at some point in the not-too-distant future.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003ePostCSS post-processing\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://gohugo.io/functions/css/postcss/\" rel=\"noopener\"\u003eWorks well with Hugo Pipes\u003c/a\u003e but, due to PostCSS\u0026rsquo;s JavaScript foundation, is \u003cstrong\u003emuch\u003c/strong\u003e slower than the other options described here.\u003c/li\u003e\n\u003cli\u003eUses various \u003ca href=\"https://postcss.org/docs/postcss-plugins\" rel=\"noopener\"\u003eplugins\u003c/a\u003e to:\n\u003cul\u003e\n\u003cli\u003ePerform transpilation, polyfills, and browser-prefixing for older browsers.\u003c/li\u003e\n\u003cli\u003eProvide bundling through a plugin\u0026rsquo;s interpretation of CSS\u0026rsquo;s \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@import\" rel=\"noopener\"\u003e\u003ccode\u003e@import\u003c/code\u003e\u003c/a\u003e command.\u003c/li\u003e\n\u003cli\u003ePerform minification.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eLightning CSS post-processing\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eMust be \u003ca href=\"/posts/2024/02/using-lightning-css-hugo-without-workarounds/\"\u003e\u0026ldquo;shoehorned\u0026rdquo; into Hugo\u003c/a\u003e. Also, Lightning CSS \u003ca href=\"https://github.com/parcel-bundler/lightningcss/issues/126\" rel=\"noopener\"\u003ehas no file-\u0026ldquo;watching\u0026rdquo; capability\u003c/a\u003e for use during development, so that, too, must be part of the \u0026ldquo;shoehorning.\u0026rdquo;\u003csup id=\"fnref:2\"\u003e\u003ca href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e2\u003c/a\u003e\u003c/sup\u003e To be fair, though, the Rust-based Lightning CSS is very fast (although not as fast as either \u003ccode\u003ecss.Build\u003c/code\u003e or Dart Sass) when properly \u0026ldquo;shoehorned.\u0026rdquo;\u003c/li\u003e\n\u003cli\u003ePerforms transpilation, polyfills, and browser-prefixing for older browsers.\u003c/li\u003e\n\u003cli\u003eProvides bundling through Lightning CSS\u0026rsquo;s interpretation of CSS\u0026rsquo;s \u003ccode\u003e@import\u003c/code\u003e command.\u003c/li\u003e\n\u003cli\u003ePerforms minification.\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"footnotes\" role=\"doc-endnotes\"\u003e\n\u003chr\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003eFor my own lightly visited, non-commercial site with its relatively simple styling, I\u0026rsquo;ve determined that \u003ca href=\"https://web.dev/baseline/2024\" rel=\"noopener\"\u003eBaseline 2024\u003c/a\u003e will suffice; but those of you with more heavily visited sites, especially if they\u0026rsquo;re commercial in nature, may well want to use additional post-processing to accommodate older and/or less commonly used browser versions.\u0026#160;\u003ca href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli id=\"fn:2\"\u003e\n\u003cp\u003eThis is as opposed to how Lightning CSS works with some other static site generators, \u003ca href=\"https://lightningcss.dev/docs.html#with-vite\" rel=\"noopener\"\u003eespecially\u003c/a\u003e if \u003ca href=\"https://vite.dev/\" rel=\"noopener\"\u003eVite\u003c/a\u003e is involved.\u0026#160;\u003ca href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“Hugo’s new CSS powers”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"},{"title":"Mixed nuts #17","date_published":"2026-03-16T16:46:00-05:00","id":"https://www.brycewray.com/posts/2026/03/mixed-nuts-17/","url":"https://www.brycewray.com/posts/2026/03/mixed-nuts-17/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"A new name for Eleventy, trying CachyOS, some new powers for Hugo, and other folderol from my noggin.","content_html":"\u003cem\u003eA new name for Eleventy, trying CachyOS, some new powers for Hugo, and other folderol from my noggin.\u003c/em\u003e\u003chr /\u003e\u003cp\u003eHere we go \u003ca href=\"/posts/2025/09/mixed-nuts-16/\"\u003eonce again\u003c/a\u003e with an entry in my \u0026ldquo;Mixed nuts\u0026rdquo; series of posts, each of which contains musings on multiple topics that have recently occupied my semi-reasonable facsimile of a brain.\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003ePerhaps soon we\u0026rsquo;ll be referring to \u0026ldquo;the static site generator \u003ca href=\"https://everything2.com/title/The\u0026#43;Artist\u0026#43;Formerly\u0026#43;Known\u0026#43;as\u0026#43;Prince\" rel=\"noopener\"\u003eformerly known as\u003c/a\u003e Eleventy,\u0026rdquo; at least in jest, but it will be true. Eleventy\u0026rsquo;s creator, Zach Leatherman, \u003ca href=\"https://www.11ty.dev/blog/build-awesome/\" rel=\"noopener\"\u003eannounced\u003c/a\u003e earlier this month that the SSG now will be called \u003cem\u003eBuild Awesome\u003c/em\u003e. You may recall that this open-source project \u003ca href=\"https://www.11ty.dev/blog/eleventy-font-awesome/\" rel=\"noopener\"\u003ecame under the aegis of Font Awesome in 2024\u003c/a\u003e, apparently settling any remaining worries about Eleventy\u0026rsquo;s long-term financial sustainability. Despite the name change, Build Awesome will remain free. However, there also will be a paid \u0026ldquo;Pro\u0026rdquo; version that will add more features; exactly which features, and what the Pro package will cost, remain TBA. (An earlier announcement, containing more details, was \u003ca href=\"https://blog.fontawesome.com/pausing-kickstarter/\" rel=\"noopener\"\u003eremoved\u003c/a\u003e.) Also, Leatherman promised to keep future versions as backward-compatible as possible with existing Eleventy sites and the current ecosphere of Eleventy plugins.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eMy \u003ca href=\"/posts/2025/08/new-life-old-mac-linux-two-years-later/\"\u003eLinux-on-the-old-Mac adventures\u003c/a\u003e continue. Now, after about a year and a half on \u003ca href=\"https://fedoraproject.org/\" rel=\"noopener\"\u003eFedora\u003c/a\u003e, I\u0026rsquo;m running the \u003ca href=\"https://archlinux.org\" rel=\"noopener\"\u003eArch\u003c/a\u003e-based \u003ca href=\"https://cachyos.org/\" rel=\"noopener\"\u003eCachyOS\u003c/a\u003e distribution. Its purpose is to provide the flexibility of Arch Linux, but with greater ease of use \u003cstrong\u003eplus\u003c/strong\u003e \u0026mdash; and this is what got me to try it \u0026mdash; special enhancements to optimize performance. It\u0026rsquo;s early, but I\u0026rsquo;ve been quite pleased with CachyOS. It seems to have many of the aspects I preferred about Arch compared to Fedora, such as \u003cstrong\u003efar\u003c/strong\u003e faster mirrors when it\u0026rsquo;s update time, yet without my having to tinker quite so much to keep things running smoothly.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eWhile I was starting to draft this post, the \u003ca href=\"https://gohugo.io\" rel=\"noopener\"\u003eHugo\u003c/a\u003e team released \u003ca href=\"https://github.com/gohugoio/hugo/releases/tag/v0.158.0\" rel=\"noopener\"\u003ev.0.158.0\u003c/a\u003e, the most interesting new feature (IMHO) of which is called \u003ccode\u003ecss.Build\u003c/code\u003e. As the \u003ca href=\"https://gohugo.io/functions/css/build/\" rel=\"noopener\"\u003edocumentation\u003c/a\u003e says, \u003ccode\u003ecss.Build\u003c/code\u003e lets you \u0026ldquo;bundle, transform, and minify CSS resources\u0026rdquo; \u0026mdash; which, up to now, I\u0026rsquo;ve been using a combination of \u003ca href=\"https://postcss.org\" rel=\"noopener\"\u003ePostCSS\u003c/a\u003e plugins and bespoke code to do, especially in production. Now, Hugo can do all those things on its own! Indeed, after spending a couple of hours fixing a few things in my existing layout files, I was able to go Hugo-only for handling the site\u0026rsquo;s styling even in production. If you\u0026rsquo;re a fellow Hugo user, I suggest you view the docs and see if you might be similarly interested.\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eI recently put aside this site\u0026rsquo;s Sass files after realizing I had little or no remaining reason to keep maintaining them. Sass long ago lost its main advantage for me over vanilla CSS, namely the nesting that \u003ca href=\"https://drafts.csswg.org/css-nesting/\" rel=\"noopener\"\u003ebecame native\u003c/a\u003e to the latter years ago; so continuing to keep around the Sass versions of my CSS files, much less having to change them for consistency\u0026rsquo;s sake every time I edited their CSS counterparts, had ceased to be anything other than a nuisance.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThe growing weight of \u0026ldquo;you-must-use-AI-no-matter-what\u0026rdquo; demands upon developers by various firms\u0026rsquo; IT overseers makes me ever gladder that I \u003ca href=\"/posts/2021/09/transition/\"\u003eretired\u003c/a\u003e well before the craze ramped up to today\u0026rsquo;s cacophonous level. My final job was mainly managing websites and the servers on which they were living, so I \u003cstrong\u003emight\u003c/strong\u003e have escaped the worst of the madness at first, but that relative calm wouldn\u0026rsquo;t have lasted. After all, when a company spends big bucks to make a Thing available to its IT team, the folks on that IT team had better-by-God be using the Thing if they know what\u0026rsquo;s good for them.\u003c/p\u003e\n\u003cdiv class=\"footnotes\" role=\"doc-endnotes\"\u003e\n\u003chr\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003ePlease note that, starting with Hugo 0.158.0, there are some important deprecations that you may have to address in your site, as Hugo contributor Joe Mooring explained in a \u003ca href=\"https://discourse.gohugo.io/t/deprecations-in-v0-158-0/56869\" rel=\"noopener\"\u003epost\u003c/a\u003e on the Hugo Discourse. For example, I had to change all my \u003ccode\u003eSite.LanguageCode\u003c/code\u003e references to \u003ccode\u003eSite.Language.Locale\u003c/code\u003e, and that\u0026rsquo;s for a site that \u003cem\u003eisn\u0026rsquo;t\u003c/em\u003e multi-lingual; on one that is, there likely will be quite a few more such changes to make.\u0026#160;\u003ca href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\n\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“Mixed nuts #17”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"},{"title":"Browsing tips","date_published":"2026-02-19T16:00:00-06:00","id":"https://www.brycewray.com/posts/2026/02/browsing-tips/","url":"https://www.brycewray.com/posts/2026/02/browsing-tips/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"Some suggestions for making websites easier to read — in more ways than one.","content_html":"\u003cem\u003eSome suggestions for making websites easier to read — in more ways than one.\u003c/em\u003e\u003chr /\u003e\u003cp\u003eIf you spend lots of hours per week perusing content on one or more web browsers as I\u0026rsquo;ve been doing since, oh, the mid-1990s, there are ways you can tailor that activity somewhat more to your liking. Many of you probably already know about the potential solutions I\u0026rsquo;ll mention in this post but, on the off-chance that you don\u0026rsquo;t, here are some tips for improving your browsing experience. Specifically, this is about: (1.) adjusting how the browsers actually render web pages; and (2.) filtering out ads and certain other content types that interfere with one\u0026rsquo;s browsing pleasure. To be sure, there\u0026rsquo;s a certain degree of interaction between those two, but I\u0026rsquo;ve found that they require two different sets of solutions.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003e(This is almost entirely about browsing from a computer, not from within a phone or tablet, particularly since the vast majority of my readers still view my content from their computers rather than their other devices. However, I still will have a few comments about browsing with the latter.)\u003c/em\u003e\u003c/p\u003e\n\u003ch2 id=\"controlling-appearances\"\u003e\u003ca class=\"header-anchor\" href=\"#controlling-appearances\"\u003eControlling appearances\u003c/a\u003e\u003c/h2\u003e\u003cp\u003eA few months ago, I noticed that I was constantly editing certain sites\u0026rsquo; CSS in the browser Inspector because, more and more, the sites\u0026rsquo; default styles were unkind to my aging eyes. Hacker News is a particularly onerous offender in this regard. For example, HN\u0026rsquo;s default shows sharply downrated comments in so light a gray color \u0026mdash; on top of a very light tan background, to boot \u0026mdash; that they\u0026rsquo;re almost illegible to me. (While I often agree that such a comment \u003cstrong\u003edeserves\u003c/strong\u003e its bad numbers, I still want at least to see what it said.) In addition, given the lighting conditions in my usual spot for viewing HN content, I prefer to see it in dark mode; but HN\u0026rsquo;s default styling doesn\u0026rsquo;t \u0026ldquo;respect\u0026rdquo; one\u0026rsquo;s dark- or light-mode settings. To paraphrase \u003ca href=\"https://www.gardnerweb.com/articles/henry-ford-is-still-right-when-it-comes-to-color\" rel=\"noopener\"\u003ean already often-paraphrased Henry Ford quote\u003c/a\u003e, \u0026ldquo;You can have any mode you want, as long as it\u0026rsquo;s light.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003eThat kind of manual, \u003cem\u003epage-by-page\u003c/em\u003e editing gets old fast, especially when you\u0026rsquo;re doing it many times a day; and HN isn\u0026rsquo;t the only such trouble spot for me. So, I soon realized, a better solution would do it in a way that works every time I go to a site. That led me to the \u003ca href=\"https://github.com/openstyles/stylus\" rel=\"noopener\"\u003eopen-source Stylus browser extension\u003c/a\u003e for Chrome- and Firefox-compatible browsers. It automatically loads site-specific CSS, rather than my making manual edits every page visit.\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e\u003c/p\u003e\n\u003cp\u003eThe interest in doing this sort of thing isn\u0026rsquo;t new, of course. Back in the early days of Firefox\u0026rsquo;s existence, We Of A Certain Age would use an extension called \u003ca href=\"https://github.com/greasemonkey/greasemonkey\" rel=\"noopener\"\u003eGreasemonkey\u003c/a\u003e which, I was delighted to see when researching for this post, is still around, although it and Firefox certainly aren\u0026rsquo;t nearly as popular as each once was. It allows customization of not only a web page\u0026rsquo;s appearance but also its functionality. \u003ca href=\"https://wiki.greasespot.net/Main_Page\" rel=\"noopener\"\u003eGreasemonkey\u0026rsquo;s wiki\u003c/a\u003e is probably the best place to go if you need a better explanation.\u003c/p\u003e\n\u003cp\u003eWhere changing only a page\u0026rsquo;s CSS is the intended result, there\u0026rsquo;ve been other notable extensions over the years:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe venerable \u003ca href=\"https://userstyles.org/\" rel=\"noopener\"\u003eStylish\u003c/a\u003e began \u003ca href=\"https://web.archive.org/web/20051210042217/http://forums.mozillazine.org/viewtopic.php?t=327735\" rel=\"noopener\"\u003ein 2005\u003c/a\u003e as an open-source project, but was acquired in 2017 by an advertising analytics company. As can sometimes result unfortunately from that type of acquisition, Stylish since has become infamous for significant privacy violations (\u003cem\u003ee.g.\u003c/em\u003e, see \u003ca href=\"https://robertheaton.com/2018/07/02/stylish-browser-extension-steals-your-internet-history/\" rel=\"noopener\"\u003ethis 2018 article\u003c/a\u003e). Even to this day, more than a few reviewers flatly call it \u0026ldquo;spyware\u0026rdquo; and downrate it severely. You can do better than Stylish.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://stylebot.dev/\" rel=\"noopener\"\u003eStylebot\u003c/a\u003e used to be one of the favorites for this sort of thing, but it hasn\u0026rsquo;t had a new release \u003cstrong\u003eon its repo\u003c/strong\u003e since \u003ca href=\"https://github.com/ankit/stylebot/releases\" rel=\"noopener\"\u003ev.3.0.1 appeared 2020-07-29\u003c/a\u003e. As of this writing, Stylebot\u0026rsquo;s Chrome extension is at v3.1.4 from 2024-05-17 and its Firefox extension is at v.3.1.3 from 2024-07-24; I\u0026rsquo;m thus presuming anything newer than v.3.0.1 is closed-source.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eBy contrast, Stylus is still actively developed and open-source, so it\u0026rsquo;s the choice I recommend.\u003c/p\u003e\n\u003cp\u003eWith Stylus, I can change the appearance of Hacker News from this:\u003c/p\u003e\n\u003cdiv class=\"relative big-img-div imgB-9401afdf23c4d2ac8756aebe0057ebec-GIP\" data-pagefind-ignore\u003e\n\t\t\t\u003cpicture data-pagefind-ignore\u003e\n\t\t\t\t\u003csource type=\"image/webp\" srcset=\"/posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_d638c92f80830cdf.webp 320w, /posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_2fe41aa54ad2cedb.webp 640w, /posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_dcee9fd6db8033f7.webp 960w, /posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_eceb5ed26dd51c37.webp 1280w, /posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_9e05ed954fa71e4f.webp 1600w, /posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_4f500c0791269b4.webp 1920w\" sizes=\"auto, (min-width: 1024px) 100vw, 50vw\" /\u003e\n\t\t\t\t\u003csource type=\"image/jpeg\" srcset=\"/posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_a4c1e90bd36066f3.jpg 320w, /posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_b8348fab3c8baa75.jpg 640w, /posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_c2f572411e871d4.jpg 960w, /posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_47fa3201fa4c7ebe.jpg 1280w, /posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_b829c29a8908b84.jpg 1600w, /posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_7c7ad052c11e522d.jpg 1920w\" sizes=\"auto, (min-width: 1024px) 100vw, 50vw\" /\u003e\n\t\t\t\t\u003cimg class=\"w-full h-auto shadow animate-fade\" src=\"/posts/2026/02/browsing-tips/HN-without-Stylus-CSS_2820x1882_hu_b8348fab3c8baa75.jpg\" width=\"2820\" height=\"1882\" alt=\"Screen capture of Hacker News without CSS changes in Stylus\" title=\"Screen capture of Hacker News without CSS changes in Stylus\" loading=\"lazy\" data-pagefind-ignore /\u003e\n\t\t\t\u003c/picture\u003e\n\t\t\u003c/div\u003e\n\u003cp\u003e. . . to this:\u003c/p\u003e\n\u003cdiv class=\"relative big-img-div imgB-edeff9293da89b1e810c0791fe884c74-GIP\" data-pagefind-ignore\u003e\n\t\t\t\u003cpicture data-pagefind-ignore\u003e\n\t\t\t\t\u003csource type=\"image/webp\" srcset=\"/posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_bea3028711886ea0.webp 320w, /posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_b7cf71ed63bc15de.webp 640w, /posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_d192798fb86b3667.webp 960w, /posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_cfc7cf78311ee4fa.webp 1280w, /posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_13cbad10cecc15e1.webp 1600w, /posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_72b25c86eb7a88dd.webp 1920w\" sizes=\"auto, (min-width: 1024px) 100vw, 50vw\" /\u003e\n\t\t\t\t\u003csource type=\"image/jpeg\" srcset=\"/posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_9c5a184acc7022e5.jpg 320w, /posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_cebb742f04a7f8f0.jpg 640w, /posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_73b48facd91e1434.jpg 960w, /posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_739c7ae4910fe6a9.jpg 1280w, /posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_79ede637c4c3ee4e.jpg 1600w, /posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_eb9e7fa1aaff38a.jpg 1920w\" sizes=\"auto, (min-width: 1024px) 100vw, 50vw\" /\u003e\n\t\t\t\t\u003cimg class=\"w-full h-auto shadow animate-fade\" src=\"/posts/2026/02/browsing-tips/HN-with-Stylus_CSS_2846x1888_hu_cebb742f04a7f8f0.jpg\" width=\"2846\" height=\"1888\" alt=\"Screen capture of Hacker News with CSS changes in Stylus\" title=\"Screen capture of Hacker News with CSS changes in Stylus\" loading=\"lazy\" data-pagefind-ignore /\u003e\n\t\t\t\u003c/picture\u003e\n\t\t\u003c/div\u003e\n\u003cp class=\"box\"\u003e\u003cstrong\u003eNote\u003c/strong\u003e: I use browsers\u0026rsquo; zoom functions to view each HN page at higher magnification because, as I said, my eyes are old. I find the default text size on many web pages to be unacceptably small and, when I inspect their CSS, what I find leads me to believe they were designed by young folks for whom It Looks OK To Them. I was inveighing against such short-sightedness \u003ca href=\"/posts/2018/10/web-typography-part-1/\"\u003eyears ago\u003c/a\u003e, even before my eyes needed as much help as they now do.\u003c/p\u003e\n\u003cp\u003eIn case you\u0026rsquo;d find it useful, here\u0026rsquo;s the CSS I use with Stylus to view Hacker News content that way:\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ehtml\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003efilter\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"nb\"\u003einvert\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e90\u003c/span\u003e\u003cspan class=\"kt\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"nb\"\u003ehue-rotate\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e180\u003c/span\u003e\u003cspan class=\"kt\"\u003edeg\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ebackground\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#fff\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"c\"\u003e/* For viewing ALWAYS in dark mode */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"c\"\u003e/* h/t to https://news.ycombinator.com/item?id=46663782 */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003etable\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003efatitem\u003c/span\u003e \u003cspan class=\"nt\"\u003ep\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003etable\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003efatitem\u003c/span\u003e \u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003etoptext\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#000\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e \u003cspan class=\"nt\"\u003ediv\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e \u003cspan class=\"nt\"\u003ediv\u003c/span\u003e \u003cspan class=\"nt\"\u003ep\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#00008b\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec5A\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#5a0000\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec73\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#730000\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec88\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#880000\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec9C\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#9c0000\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecAE\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#ae0000\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecBE\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#be0000\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecCE\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#ce0000\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecDD\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#dd0000\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec00\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#00008b\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec5A\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec73\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec88\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec9C\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecAE\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecBE\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecCE\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecDD\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#8b0000\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec5A\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nd\"\u003evisited\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec73\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nd\"\u003evisited\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec88\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nd\"\u003evisited\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec9C\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nd\"\u003evisited\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecAE\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nd\"\u003evisited\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecBE\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nd\"\u003evisited\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecCE\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nd\"\u003evisited\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecDD\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nd\"\u003evisited\u003c/span\u003e\u003cspan class=\"o\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ecommtext\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003ec00\u003c/span\u003e \u003cspan class=\"nt\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"nd\"\u003evisited\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#8b008b\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e \u003cspan class=\"nt\"\u003ediv\u003c/span\u003e \u003cspan class=\"nt\"\u003epre\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"k\"\u003ecolor\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mh\"\u003e#006400\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eWhere Apple\u0026rsquo;s WebKit-based Safari browser is concerned, the outlook is more grim: there is no Stylus extension  for Safari, for which \u003ca href=\"https://www.howtogeek.com/safari-is-missing-your-favorite-extensions/\" rel=\"noopener\"\u003ethird-party extension availability is much more limited\u003c/a\u003e.\u003csup id=\"fnref:2\"\u003e\u003ca href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e2\u003c/a\u003e\u003c/sup\u003e The closed-source, paid \u003ca href=\"https://apps.apple.com/us/app/cascadea/id1432182561?mt=12\" rel=\"noopener\"\u003eCascadea\u003c/a\u003e extension for Safari on macOS would \u003cem\u003eseem\u003c/em\u003e to provide similar capabilities (I haven\u0026rsquo;t tried it), but its last update was apparently 2021-11-02.\u003c/p\u003e\n\u003cp class=\"box\"\u003e\u003cstrong\u003eUpdate, 2026-05-29\u003c/strong\u003e: I later learned of a paid Safari extension called \u003ca href=\"https://getnoir.app\" rel=\"noopener\"\u003eNoir\u003c/a\u003e that provides a less customizable, but helpful, dark-mode experience on sites which otherwise don\u0026rsquo;t respect one\u0026rsquo;s viewing preferences.\u003c/p\u003e\n\u003cp\u003eIf you\u0026rsquo;re on macOS and prefer to avoid Chrome- and Firefox-compatible browsers, there \u003cem\u003emay\u003c/em\u003e be another possibility. The \u003ca href=\"https://orionbrowser.com/\" rel=\"noopener\"\u003eOrion\u003c/a\u003e browser, also based on WebKit, actually allows the enabling of extensions built for Chrome and Firefox, although many such extensions\u0026rsquo; actual in-Orion performance remains problematic at this writing. You can \u003cem\u003etry\u003c/em\u003e using an older version of the Stylus extension for Chrome \u0026mdash; I got it to work on Orion with v.1.5.51 \u0026mdash; since anything newer apparently isn\u0026rsquo;t compatible with Orion. It\u0026rsquo;s possible to \u003cem\u003einstall\u003c/em\u003e the current Stylus version, but its functionality is broken in Orion.\u003c/p\u003e\n\u003ch2 id=\"blocking-ads\"\u003e\u003ca class=\"header-anchor\" href=\"#blocking-ads\"\u003eBlocking ads\u003c/a\u003e\u003c/h2\u003e\u003cp\u003eObviously, the existence of most content I follow on the web depends to some extent on advertising dollars. Still, there\u0026rsquo;s a lot of problems with how some ads are delivered on the web these days, right down to the \u003ca href=\"https://www.securityweek.com/fbi-recommends-ad-blockers-cybercriminals-impersonate-brands-search-engine-ads/\" rel=\"noopener\"\u003einclusion of out-and-out malware\u003c/a\u003e in more than a few cases; so I choose to perform whatever ad-blocking I can. Besides, there are hundreds of millions of young folks out there using their totally non-ad-blocked phones to cruise the InterWebz, so I\u0026rsquo;m sure old goats such as I are no longer that important to the poor, oppressed advertisers. They won\u0026rsquo;t miss me. I surely don\u0026rsquo;t miss them.\u003c/p\u003e\n\u003cp\u003eAs with the CSS-editing stuff I described earlier, my approach to blocking ads is \u003cem\u003emostly\u003c/em\u003e extension-based. The best ad-blocker out there is \u003ca href=\"https://github.com/gorhill\" rel=\"noopener\"\u003eRaymond Hill\u003c/a\u003e\u0026rsquo;s superb open-source extension, \u003ca href=\"https://github.com/uBlockOrigin\" rel=\"noopener\"\u003euBlock Origin\u003c/a\u003e. Although uBO \u003ca href=\"https://github.com/gorhill/uBlock/wiki/uBlock-Origin-works-best-on-Firefox\" rel=\"noopener\"\u003ehas always worked best on Firefox\u003c/a\u003e, it also was a must-install on Chrome until 2024. That\u0026rsquo;s when Google began implementing its \u003ca href=\"https://developer.chrome.com/docs/extensions/develop/migrate/what-is-mv3\" rel=\"noopener\"\u003eManifest V3 extension platform\u003c/a\u003e which, combined with similar developments in other browsers (some earlier, as in the case of Safari), \u003ca href=\"https://github.com/uBlockOrigin/uBlock-issues/wiki/About-Google-Chrome%27s-%22This-extension-may-soon-no-longer-be-supported%22\" rel=\"noopener\"\u003eneutered how uBO works\u003c/a\u003e due to the blocking of certain network requests upon which uBO\u0026rsquo;s blocking and filtering depends.  As a result, Hill came up with the Manifest V3-compatible (and therefore more limited) \u003ca href=\"https://github.com/uBlockOrigin/uBOL-home\" rel=\"noopener\"\u003euBlock Origin Lite\u003c/a\u003e for Chrome-compatible browsers and, more recently, Safari. In my own use cases, uBOL works better than a lot of people think and certainly is better than no ad-blocker at all on those browsers, although it surely doesn\u0026rsquo;t \u0026ldquo;catch\u0026rdquo; as much as the real uBO still does in Firefox.\u003c/p\u003e\n\u003cp\u003eFor fans of Chrome-compatible browsers, the Brave browser gives you nearly uBO-like ad-blocking and content-filtering through its built-in, Rust-powered \u003ca href=\"https://brave.com/shields/\" rel=\"noopener\"\u003eBrave Shields\u003c/a\u003e feature, some settings for which \u0026mdash; notably, its \u003ca href=\"https://support.brave.app/hc/en-us/articles/6449369961741-How-do-I-manage-adblock-filters-in-Brave\" rel=\"noopener\"\u003efilter lists\u003c/a\u003e \u0026mdash; are largely compatible with similar settings for uBO and certain other blockers, such as \u003ca href=\"https://getadblock.com/en/\" rel=\"noopener\"\u003eAdBlock\u003c/a\u003e. (As you\u0026rsquo;ve probably read elsewhere, Brave \u003cem\u003edoes\u003c/em\u003e still support full-fledged uBO, at least for now, \u003cstrong\u003ebut\u003c/strong\u003e the widespread advice is not to use both Brave Shields and uBO together; the former is sufficient.)\u003c/p\u003e\n\u003cp\u003eAs mentioned above, the Orion browser on macOS allows use of some extensions from the respective Chrome and Firefox web stores; and, as of this writing, the full-fledged uBO extension for Firefox still works with Orion. How long that will still be true (\u003cem\u003ei.e.\u003c/em\u003e, whether a Manifest V3-like situation catches up with Orion at some point) remains to be seen.\u003c/p\u003e\n\u003cp\u003eWhere Safari is concerned, there are two other possibilities you can try, each of which is free/open-source and works by performing ad-blocking and content-filtering at the device level, rather than the browser level:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/0xCUB3/wBlock\" rel=\"noopener\"\u003ewBlock\u003c/a\u003e is available for macOS, iOS, and iPadOS. Its \u003ca href=\"https://github.com/0xCUB3/wBlock/blob/main/Adblock_Comparison.md#feature-comparison\" rel=\"noopener\"\u003efeature comparison chart\u003c/a\u003e lets you see how it stacks up against several other, better-known ad-blocking solutions for Safari, including uBOL. By being a device-level ad-blocker rather than a browser extension, it avoids the limitations that would hamper a uBO-like blocker while working \u0026mdash; at least, in my own observations over the last few weeks \u0026mdash; quite well on all my Apple devices. If Safari is a sufficient browsing experience for you, I can recommend wBlock quite highly. (For just one example: before I installed wBlock, I found it unbearable to view Reddit on Safari.)\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/ZenPrivacy/zen-desktop\" rel=\"noopener\"\u003eZen\u003c/a\u003e, which probably should be called something else so it\u0026rsquo;s easier to find in a web search (since there\u0026rsquo;s already a popular Firefox fork called Zen), is available for macOS as well as Windows and Linux; to my knowledge, there\u0026rsquo;s no mobile version at this time. It blocks ads and the like from \u003cem\u003eall\u003c/em\u003e browsers, not just Safari as is the case with wBlock. While I found Zen to be competent enough \u0026mdash; \u003cem\u003ee.g.\u003c/em\u003e, it blocks more from Chrome than uBOL does \u0026mdash; it also seems to have some technical quirks that made me stop using it after a few days of testing. One glitch that bugged me in particular was that it seems to interfere with certain HTTP requests in such a way that HTTP/3 content was dropped down to HTTP/1.1. (Yeah, \u003ca href=\"/posts/2025/10/getting-http3-cloudflare-firefox/\"\u003eI do care about that sort of thing\u003c/a\u003e.) Still, it\u0026rsquo;s a fairly young project compared to others in this genre, so perhaps such issues will lessen over time. (I did find some online comments lamenting Zen\u0026rsquo;s requirement to install a local root certificate; while its documentation does \u003ca href=\"https://github.com/ZenPrivacy/zen-desktop/blob/master/docs/internal/security-architecture.md\" rel=\"noopener\"\u003eexplain this rather fully\u003c/a\u003e, some individuals fully \u0026ldquo;noped out\u0026rdquo; of it over just that item.)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"box\"\u003e\u003cstrong\u003eNote\u003c/strong\u003e: Finally, since I suspect at least one visitor will wonder about it . . . yes, I do know about \u003ca href=\"https://www.zdnet.com/article/sick-of-online-ads-and-trackers-how-i-block-them-across-my-entire-home-network/\" rel=\"noopener\"\u003erouter-level ad-blocking\u003c/a\u003e, but it simply involves more futzing than I care to do. I\u0026rsquo;ll tinker with \u003cstrong\u003emy\u003c/strong\u003e computers, devices, and/or browsers to get desired ad-blocking results, because I\u0026rsquo;m the only one who will suffer if I err; but I won\u0026rsquo;t Go There where \u003cstrong\u003eour\u003c/strong\u003e shared TV is concerned. Maybe a twenty-years-younger version of me would\u0026rsquo;ve tried something like that, but the 2026 version of me neither cares that much about it nor needs the potential, resulting headaches.\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003eIf you feel any or all of the above suggestions will be more of a hassle than you have either time or patience to handle, don\u0026rsquo;t worry. It simply means you\u0026rsquo;re not as cantankerous as I, and that\u0026rsquo;s probably a good thing. However, if you \u003cem\u003eare\u003c/em\u003e willing to give these a try, I think you\u0026rsquo;ll like the results. They took a while to get the way I wanted them \u0026mdash; and I\u0026rsquo;m still making adjustments here and there \u0026mdash; but I\u0026rsquo;ve found them quite worth the time and effort. I hope you will, too.\u003c/p\u003e\n\u003cdiv class=\"footnotes\" role=\"doc-endnotes\"\u003e\n\u003chr\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003eIf you use only Firefox-compatible browsers, you can do this by creating and editing a \u003ccode\u003euserContent.css\u003c/code\u003e file. That method certainly has its adherents, but I prefer using an extension like Stylus rather than maintaining a local file, especially since \u003ca href=\"https://bugzilla.mozilla.org/show_bug.cgi?id=1541233\" rel=\"noopener\"\u003eMozilla long ago put the use of that file behind a flag\u003c/a\u003e and could kill it at any time.\u0026#160;\u003ca href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli id=\"fn:2\"\u003e\n\u003cp\u003eMany years ago, even the now-tarnished Stylish had a Safari version!\u0026#160;\u003ca href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“Browsing tips”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"},{"title":"Three items of note","date_published":"2026-01-21T16:57:00-06:00","id":"https://www.brycewray.com/posts/2026/01/three-items-note/","url":"https://www.brycewray.com/posts/2026/01/three-items-note/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"The Cloudflare acquihire of Astro, visited links of a not-different color, and a 1Password syntax highlighting bug.","content_html":"\u003cem\u003eThe Cloudflare acquihire of Astro, visited links of a not-different color, and a 1Password syntax highlighting bug.\u003c/em\u003e\u003chr /\u003e\u003cp\u003eSince I last wrote herein, three events have piqued my nerdy curiosity, suggesting some appropriate musings on them. The first affects the web development business; the second has to do with a change in how visited links look in some web browsers; and the third concerns a browser extension bug which, for a few weeks, fouled up code blocks in some websites (including this one).\u003c/p\u003e\n\u003ch2 id=\"cloudflare-acquihires-astro\"\u003e\u003ca class=\"header-anchor\" href=\"#cloudflare-acquihires-astro\"\u003eCloudflare acquihires Astro\u003c/a\u003e\u003c/h2\u003e\u003cp\u003eAmong the tools I\u0026rsquo;ve used over the years to build and maintain this site, one of the more interesting is \u003ca href=\"https://astro.build\" rel=\"noopener\"\u003eAstro\u003c/a\u003e. This open-source framework has come a long way since its beta versions, which with I tinkered a few years ago; and, in the process, it\u0026rsquo;s gained a ton of support among the web dev community. However, that support apparently never translated to a revenue stream that would sustain either Astro itself or the Astro Technology Company which employed a substantial number of the folks behind Astro. The resulting financial shortfall risked Astro\u0026rsquo;s perhaps becoming abandonware in the not-too-distant future; that would have been a sad ending to a greatly admired project.\u003c/p\u003e\n\u003cp\u003eAs a result, according to \u003ca href=\"https://blog.cloudflare.com/astro-joins-cloudflare/\" rel=\"noopener\"\u003ejointly\u003c/a\u003e \u003ca href=\"https://astro.build/blog/joining-cloudflare/\" rel=\"noopener\"\u003ereleased\u003c/a\u003e blog posts, \u003ca href=\"https://www.cloudflare.com\" rel=\"noopener\"\u003eCloudflare\u003c/a\u003e has \u003ca href=\"https://dictionary.cambridge.org/us/dictionary/english/acqui-hire\" rel=\"noopener\"\u003eacquihired\u003c/a\u003e the Astro Technology Company. Although not all acquihires are good for the object of said events, this one \u0026mdash; \u003cem\u003eat least for now\u003c/em\u003e \u0026mdash; looks like a win-win. Cloudflare gets to own a solid and popular development framework (much like \u003ca href=\"https://vercel.com\" rel=\"noopener\"\u003eVercel\u003c/a\u003e owns \u003ca href=\"https://nextjs.org\" rel=\"noopener\"\u003eNext.js\u003c/a\u003e), and the Astro team gets to keep that framework growing and improving.\u003c/p\u003e\n\u003ch2 id=\"visited-links-on-blink-based-browsers\"\u003e\u003ca class=\"header-anchor\" href=\"#visited-links-on-blink-based-browsers\"\u003eVisited links on Blink-based browsers\u003c/a\u003e\u003c/h2\u003e\u003cp\u003eTurns out I missed a change from last April that affects the color of visited links in a \u003ca href=\"https://www.chromium.org/blink/\" rel=\"noopener\"\u003eBlink\u003c/a\u003e-based browser such as Chrome or Chromium. In the early days of the web, a link you hadn\u0026rsquo;t yet visited in a given browser would always be a bright blue color (\u003ccode\u003e#0000ff\u003c/code\u003e) while one you \u003cem\u003ehad\u003c/em\u003e visited therein would be purplish (\u003ccode\u003e#800080\u003c/code\u003e). More to the point, a visited link would be that purplish color regardless of which originating page had gotten you there.\u003c/p\u003e\n\u003cp\u003eFor example: if you were on \u003ccode\u003efoo.com\u003c/code\u003e and clicked a link to \u003ccode\u003ebar.com\u003c/code\u003e, you would subsequently see that \u003ccode\u003ebar.com\u003c/code\u003e link in the purplish color on \u003cstrong\u003eany other\u003c/strong\u003e page, not just on \u003ccode\u003efoo.com\u003c/code\u003e, as long as the browser still kept that visit in its history. Of course, over time, websites have gotten a lot more creative about their various link colors \u003cstrong\u003ebut\u003c/strong\u003e the behavior remained the same.\u003c/p\u003e\n\u003cp\u003eOr, at least, it did \u003cstrong\u003euntil\u003c/strong\u003e last April\u0026rsquo;s release of Chromium 136. Now, with any browser based on that version or later, you\u0026rsquo;ll \u0026ldquo;see\u0026rdquo; the visited link as visited \u003cstrong\u003eonly\u003c/strong\u003e if that visit came from the site you\u0026rsquo;re viewing. This change, \u003ca href=\"https://developer.chrome.com/blog/visited-links\" rel=\"noopener\"\u003eattributed by Google\u003c/a\u003e to the need to firm up browser security, received attention at the time from \u003ca href=\"https://www.bleepingcomputer.com/news/security/chrome-136-fixes-20-year-browser-history-privacy-risk/\" rel=\"noopener\"\u003eBleeping Computer\u003c/a\u003e and \u003ca href=\"https://www.tomsguide.com/computing/browsers/google-will-finally-stop-this-20-year-chrome-bug-from-leaking-your-browsing-history-to-other-websites-heres-how\" rel=\"noopener\"\u003eTom\u0026rsquo;s Guide\u003c/a\u003e, among other sites.\u003c/p\u003e\n\u003cp\u003eAt this writing, only Blink-based browsers like Chrome and Chromium work this way for visited links\u0026rsquo; appearances; it remains to be seen when, or whether, \u003ca href=\"https://firefox-source-docs.mozilla.org/overview/gecko.html\" rel=\"noopener\"\u003eGecko\u003c/a\u003e- and \u003ca href=\"https://webkit.org/\" rel=\"noopener\"\u003eWebKit\u003c/a\u003e-based browsers will follow the Chromium project\u0026rsquo;s lead.\u003c/p\u003e\n\u003ch2 id=\"1password-vs-code-blocks\"\u003e\u003ca class=\"header-anchor\" href=\"#1password-vs-code-blocks\"\u003e1Password \u003cem\u003evs.\u003c/em\u003e code blocks\u003c/a\u003e\u003c/h2\u003e\u003cp\u003eMost password management apps have their own extensions for browsers, simplifying the act of entering one\u0026rsquo;s credentials when necessary. Each such extension injects some additional code into the content delivered to the browser. This usually works without interfering with the appearance of a web page but, for a few weeks last month, such was not the case following an update to the \u003ca href=\"https://1password.com\" rel=\"noopener\"\u003e1Password\u003c/a\u003e browser extension.\u003c/p\u003e\n\u003cp\u003eThe problematic version, v.8.11.23.x, totally clobbered the syntax highlighting on some (but not all) web pages with code blocks like this one, which shows a little CSS:\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"nc\"\u003esitemap-div\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"k\"\u003emargin\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e \u003cspan class=\"kc\"\u003eauto\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"k\"\u003ewidth\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e \u003cspan class=\"mi\"\u003e90\u003c/span\u003e\u003cspan class=\"kt\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eWith the buggy extension version enabled, the code block looked something like this, at least on my site:\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eAs for why, here’s an example of what the 1Password bug did to anything from the combination of \u003ca href=\"https://gohugo.io\" rel=\"noopener\"\u003eHugo\u003c/a\u003e and \u003ca href=\"https://github.com/alecthomas/chroma\" rel=\"noopener\"\u003eChroma\u003c/a\u003e. This is how a specific code block on \u003ca href=\"/posts/2025/12/new-normal-starting-hugo-0.153.x/\"\u003eone of my Hugo-generated pages\u003c/a\u003e is \u003cstrong\u003esupposed\u003c/strong\u003e to look in HTML:\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e \u003cspan class=\"na\"\u003eclass\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;highlight\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003epre\u003c/span\u003e \u003cspan class=\"na\"\u003etabindex\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;0\u0026#34;\u003c/span\u003e \u003cspan class=\"na\"\u003eclass\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;chroma\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003ecode\u003c/span\u003e \u003cspan class=\"na\"\u003eclass\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;language-plaintext\u0026#34;\u003c/span\u003e \u003cspan class=\"na\"\u003edata-lang\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;plaintext\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003espan\u003c/span\u003e \u003cspan class=\"na\"\u003eclass\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;line\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003espan\u003c/span\u003e \u003cspan class=\"na\"\u003eclass\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;cl\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            /Users/$USERNAME/Library/Caches/hvm/$HUGO_VERSION/hugo\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e          \u003cspan class=\"p\"\u003e\u0026lt;/\u003c/span\u003e\u003cspan class=\"nt\"\u003espan\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e\u0026lt;/\u003c/span\u003e\u003cspan class=\"nt\"\u003espan\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e\u0026lt;/\u003c/span\u003e\u003cspan class=\"nt\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e\u0026lt;/\u003c/span\u003e\u003cspan class=\"nt\"\u003epre\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e\u0026lt;/\u003c/span\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e\u0026lt;/\u003c/span\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003e. . . and this is the HTML for the same code block after the then-buggy 1Password extension got through with it:\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e \u003cspan class=\"na\"\u003eclass\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;highlight\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003epre\u003c/span\u003e \u003cspan class=\"na\"\u003etabindex\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;0\u0026#34;\u003c/span\u003e \u003cspan class=\"na\"\u003eclass\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;chroma language-plaintext\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003ecode\u003c/span\u003e \u003cspan class=\"na\"\u003eclass\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;language-plaintext\u0026#34;\u003c/span\u003e \u003cspan class=\"na\"\u003edata-lang\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;plaintext\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        /Users/$USERNAME/Library/Caches/hvm/$HUGO_VERSION/hugo\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e      \u003cspan class=\"p\"\u003e\u0026lt;/\u003c/span\u003e\u003cspan class=\"nt\"\u003ecode\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e\u0026lt;/\u003c/span\u003e\u003cspan class=\"nt\"\u003epre\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"p\"\u003e\u0026lt;/\u003c/span\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e\u0026lt;/\u003c/span\u003e\u003cspan class=\"nt\"\u003ediv\u003c/span\u003e\u003cspan class=\"p\"\u003e\u0026gt;\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eThose missing \u003ccode\u003espan\u003c/code\u003es obviously made a lot of difference, as did the insertion of a spurious \u003ccode\u003elanguage-plaintext\u003c/code\u003e in the \u003ccode\u003epre\u003c/code\u003e element\u0026rsquo;s \u003ccode\u003eclass\u003c/code\u003e declaration.\u003c/p\u003e\n\u003cp\u003eAs one might expect, the glitch was soon the subject of an \u003ca href=\"https://www.1password.community/discussions/developers/1password-chrome-extension-is-incorrectly-manipulating--blocks/165639\" rel=\"noopener\"\u003eactive discussion\u003c/a\u003e in the 1Password Community Forum, where one complaint after another showed screen captures of how the bug had \u0026ldquo;\u003ca href=\"https://knowyourmeme.com/memes/look-how-they-massacred-my-boy\" rel=\"noopener\"\u003emassacred their boy\u003c/a\u003e,\u0026rdquo; so to speak. What had happened? Well, based on various comments I read there and elsewhere about the issue, it appears that the buggy version was injecting the JavaScript-based \u003ca href=\"https://prismjs.com/\" rel=\"noopener\"\u003ePrism\u003c/a\u003e syntax highlighter. The additional code apparently was mistakenly left behind from a particular inter-version development test. Although some sites somehow escaped unscathed, the bug clearly caused styling conflicts with numerous other pages\u0026rsquo; own syntax highlighting code.\u003c/p\u003e\n\u003cp\u003eDespite the 1Password team\u0026rsquo;s relatively quick acknowledgement of the SNAFU, it took several days\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e before a fix arrived in the form of v.8.11.27.x, first in the Chrome Web Store and later the corresponding \u0026ldquo;stores\u0026rdquo; for Firefox and Safari; and not until \u003ca href=\"https://releases.1password.com/b5x/stable/#1password-in-the-browser-8.12.0\" rel=\"noopener\"\u003ev.8.12.0\u003c/a\u003e did the release notes mention the fix:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eWe\u0026rsquo;ve fixed an issue where the 1Password extension could break syntax highlighting for code blocks on some websites.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"footnotes\" role=\"doc-endnotes\"\u003e\n\u003chr\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003eThe delay may have been largely due to the holiday-season absence of certain 1Password devs. The Passover/Christmas/New Year\u0026rsquo;s season is almost never a good time to get anything fixed, and browser extensions are no exception to that rule.\u0026#160;\u003ca href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“Three items of note”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"},{"title":"My “new normal,” starting with Hugo 0.153.x","date_published":"2025-12-26T10:29:00-06:00","id":"https://www.brycewray.com/posts/2025/12/new-normal-starting-hugo-0.153.x/","url":"https://www.brycewray.com/posts/2025/12/new-normal-starting-hugo-0.153.x/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"Switching to hvm and converting my scripts to work with Hugo’s packaging for macOS.","content_html":"\u003cem\u003eSwitching to hvm and converting my scripts to work with Hugo’s packaging for macOS.\u003c/em\u003e\u003chr /\u003e\u003cp\u003eUntil a few days ago, those who use the \u003ca href=\"https://gohugo.io\" rel=\"noopener\"\u003eHugo\u003c/a\u003e static site generator on macOS have had to deal with Apple\u0026rsquo;s \u003ca href=\"https://eclecticlight.co/2021/12/11/explainer-quarantine/\" rel=\"noopener\"\u003equarantine feature\u003c/a\u003e each time they downloaded a new Hugo version. With the recent release of Hugo \u003ca href=\"https://github.com/gohugoio/hugo/releases/tag/v0.153.0\" rel=\"noopener\"\u003e0.153.0\u003c/a\u003e, that ceased to be the case. For most Hugo-on-macOS users, that\u0026rsquo;s a good thing. For nerds like me who\u0026rsquo;ve been managing their Hugo-on-macOS workflows through scripting, it was . . . complicated. However, with major help from one of Hugo\u0026rsquo;s key personnel, I was able to make this \u0026ldquo;new normal\u0026rdquo; a good thing for me, too.\u003c/p\u003e\n\u003cp class=\"box\"\u003e\u003cstrong\u003eUpdate, 2026-05-05\u003c/strong\u003e: After reading this, please see also a \u003ca href=\"/posts/2026/05/new-normal-update/\"\u003efollow-up post\u003c/a\u003e regarding my use of a later version of the hvm version management app discussed below.\u003c/p\u003e\n\u003ch1 id=\"dealing-with-the-packaging-change\"\u003e\u003ca class=\"header-anchor\" href=\"#dealing-with-the-packaging-change\"\u003eDealing with the packaging change\u003c/a\u003e\u003c/h1\u003e\u003cp\u003eHugo 0.153.0 changed the macOS deliverable. Where the binary used to reside in a \u003ccode\u003etar.gz\u003c/code\u003e archive, it now comes in a regular macOS \u003ccode\u003e.pkg\u003c/code\u003e that installs with a double-click. Still, it remains a terminal app and, thus, not as readily updatable as a typical macOS GUI app with a \u0026ldquo;Check for updates\u0026rdquo; menu item and associated functionality.\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e\u003c/p\u003e\n\u003cp\u003eIn a Hugo Discourse entry \u0026mdash; \u003ca href=\"https://discourse.gohugo.io/t/0-153-0-for-macos-pkg-rather-than-tar-gz/56398\" rel=\"noopener\"\u003e\u0026ldquo;0.153.0 for macOS: .pkg rather than .tar.gz\u0026rdquo;\u003c/a\u003e \u0026mdash; I asked, \u0026ldquo;what is a Best Practices way for us macOS users to handle version updates going forward?\u0026rdquo; One user suggested I use the \u003ca href=\"https://github.com/jmooring/hvm\" rel=\"noopener\"\u003ehvm\u003c/a\u003e (Hugo Version Manager) tool maintained by Hugo contributor \u003ca href=\"https://github.com/jmooring\" rel=\"noopener\"\u003eJoe Mooring\u003c/a\u003e; but, when I did, I found that it wasn\u0026rsquo;t yet able to handle this new packaging. After seeing my report to this effect, Mooring suggested I open a related issue in the hvm repo, \u003ca href=\"https://github.com/jmooring/hvm/issues/178\" rel=\"noopener\"\u003ewhich I did\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eAlso within that same Hugo Discourse discussion, Hugo maintainer Bjørn Erik Pedersen explained the reason for the packaging change:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003ePeople have been asking for a signed and notarised [macOS version] \u0026hellip; for a long time, and since Apple has tightened the security on this (you need to manually go into the security prefs and whitelist any non-signed/notarised app), I decided it was time to do it right, and that meant either pkg or dmg, and pkg is much nicer.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eI promptly replied:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eOh, please don\u0026rsquo;t misunderstand\u0026hellip; \u0026mdash; I think it\u0026rsquo;s a great idea. I\u0026rsquo;m mainly just trying to figure out how I update it locally going forward. (My old method deleted the previous version and pulled the current one, using an \u003ccode\u003exattr -dr com.apple.quarantine\u003c/code\u003e command as a workaround for just the issues you mentioned.)\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eIn the hvm issue I\u0026rsquo;d filed, Mooring and I conversed about the situation and how best to resolve it. Just four days later \u0026mdash; which, apparently, included his actually purchasing a Mac of his own (!) \u0026mdash; he updated hvm to a new version, \u003ca href=\"https://github.com/jmooring/hvm/releases/tag/v0.9.0\" rel=\"noopener\"\u003e0.9.0\u003c/a\u003e, that was able to deal with the new packaging. Because hvm allows you to install and use a new version (as well as delete any older ones, if you choose) with just a couple of keystrokes, that solved my problem regarding updates going forward.\u003c/p\u003e\n\u003ch1 id=\"fixing-my-own-scripts\"\u003e\u003ca class=\"header-anchor\" href=\"#fixing-my-own-scripts\"\u003eFixing my own scripts\u003c/a\u003e\u003c/h1\u003e\u003cp\u003eNow, my only remaining problem to solve was in my own scripting through which, up to then, I\u0026rsquo;d managed my local Hugo operations for the last couple of years.\u003c/p\u003e\n\u003cp\u003ePrior to Hugo 0.153.0, an \u003ccode\u003einstall.sh\u003c/code\u003e script about which I once \u003ca href=\"/posts/2023/06/using-dart-sass-hugo-simpler-way/\"\u003ewrote\u003c/a\u003e would download a designated Hugo version\u0026rsquo;s \u003ccode\u003e.tar.gz\u003c/code\u003e file, extract from it the Hugo binary, and place that binary in a \u003ccode\u003ebin\u003c/code\u003e directory (after deleting any other Hugo binary that might already be there).\u003csup id=\"fnref:2\"\u003e\u003ca href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e2\u003c/a\u003e\u003c/sup\u003e I have now adapted \u003ccode\u003einstall.sh\u003c/code\u003e so that, rather than downloading and extracting the former Hugo \u003ccode\u003e.tar.gz\u003c/code\u003e, it now gets the desired version of hvm\u0026rsquo;s \u003ccode\u003e.tar.gz\u003c/code\u003e, after which I use hvm as needed to manage the Hugo binary itself.\u003c/p\u003e\n\u003cp\u003eThat was easy enough to do, but my other Hugo-management scripts were another matter altogether. Because the \u003ccode\u003ebin\u003c/code\u003e directory is in my \u003ccode\u003e$PATH\u003c/code\u003e, those scripts had no trouble accessing the pre-0.153.0 Hugo binary and, thus, could run various \u003ccode\u003ehugo\u003c/code\u003e commands and their flags just fine. However, this no longer was the case with hvm, which accesses Hugo\u0026rsquo;s 0.153.0+ \u003ccode\u003e.pkg\u003c/code\u003e download and extracts the Hugo binary into:\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-plaintext\" data-lang=\"plaintext\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e/Users/$USERNAME/Library/Caches/hvm/$HUGO_VERSION/hugo\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eHere, \u003ccode\u003e$HUGO_VERSION\u003c/code\u003e is, \u003cem\u003ee.g.\u003c/em\u003e, \u003ccode\u003ev0.153.2\u003c/code\u003e, the latest Hugo version as of this writing.\u003c/p\u003e\n\u003cp\u003eWith this arrangement, I still could manually run \u003ccode\u003ehugo\u003c/code\u003e (flagged or not) from the command line with no problem, but that wasn\u0026rsquo;t true for the scripts. Specifically, I used \u003ccode\u003estart.sh\u003c/code\u003e for purely local development, \u003ccode\u003etestbuild.sh\u003c/code\u003e for local development in a production environment, and \u003ccode\u003ebuild.sh\u003c/code\u003e when I just wanted to build the site, not serve it locally. For example, \u003ccode\u003estart.sh\u003c/code\u003e had this line\u003csup id=\"fnref:3\"\u003e\u003ca href=\"#fn:3\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e3\u003c/a\u003e\u003c/sup\u003e for running the local Hugo server to my liking:\u003c/p\u003e\n\n\t\u003cdiv class=\"highlight-wide\"\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-plaintext\" data-lang=\"plaintext\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ehugo server --port 3000 --bind=0.0.0.0 --baseURL=http://${MY_IP}:3000 --panicOnWarning --forceSyncStatic --gc\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eNow, with the hvm-installed Hugo binary in its new location, the line failed to \u0026ldquo;find\u0026rdquo; the \u003ccode\u003ehugo\u003c/code\u003e command \u0026mdash; triggering that \u003ccode\u003eCommand not found\u003c/code\u003e response about which a web search for \u0026ldquo;script command not found\u0026rdquo; will tell you volumes (this \u003ca href=\"https://www.redhat.com/en/blog/fix-command-not-found-error-linux\" rel=\"noopener\"\u003eRed Hat article about resolving the issue in Linux\u003c/a\u003e is among the better sources, since macOS and Linux have a lot in common) \u0026mdash; so this errored out the script. The usual solution for this sort of thing is to hard-code the path to the Hugo binary; but, since the path would now vary based on the Hugo version that hvm was using, I initially thought I\u0026rsquo;d have to make a minor edit to each of these scripts \u003cem\u003eevery time\u003c/em\u003e I changed my Hugo version.\u003c/p\u003e\n\u003cp\u003eThen, fortunately, I remembered that hvm itself eliminates the need for such tedium.\u003c/p\u003e\n\u003cp\u003eThat\u0026rsquo;s because part of the hvm setup procedure involves source-controlling the \u003ccode\u003e.hvm\u003c/code\u003e text file that hvm will create in the top level of your Hugo project. \u003ccode\u003e.hvm\u003c/code\u003e is a one-line file listing the Hugo version you\u0026rsquo;re using. For example, the one I\u0026rsquo;m using as of this writing says only:\u003c/p\u003e\n\n\t\u003cdiv\u003e\n\t\t\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-plaintext\" data-lang=\"plaintext\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ev0.153.2\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\t\u003c/div\u003e\u003cp\u003eThis simplified my fixes to a one-time process for each of the problematic scripts:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eAdd a \u003ccode\u003eMY_PATH\u003c/code\u003e variable pointing to the contents of a \u003ccode\u003emypath.txt\u003c/code\u003e file that includes the beginning of the path to the hvm-managed Hugo binary.\u003c/li\u003e\n\u003cli\u003eAdd a \u003ccode\u003eHUGO_VERSION\u003c/code\u003e variable pointing to the contents of the \u003ccode\u003e.hvm\u003c/code\u003e file.\u003c/li\u003e\n\u003cli\u003eChange each Hugo command from just \u003ccode\u003ehugo\u003c/code\u003e to \u003ccode\u003e${MY_PATH}/hvm/${HUGO_VERSION}/hugo\u003c/code\u003e \u0026mdash; followed by whatever flags, if any, I want.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eWith those done, my scripts run as before, letting me go back to managing my Hugo setup as I prefer.\u003c/p\u003e\n\u003cp\u003eSo that\u0026rsquo;s how I\u0026rsquo;ve settled into this \u0026ldquo;new normal.\u0026rdquo;  Perhaps I\u0026rsquo;m a Cult of One in doing it my way, as I suggested to Joe Mooring in that hvm issue; but I offer this information on the chance that other macOS-using Hugo aficionados may find it of use in their own projects.\u003c/p\u003e\n\u003cdiv class=\"footnotes\" role=\"doc-endnotes\"\u003e\n\u003chr\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003eI do know that some veteran Hugo users rarely or never update their sites\u0026rsquo; Hugo versions, fearful of dealing with breaking changes (especially across multiple sites). As for my situation, this personal site is my only Hugo project, so I usually update whenever there\u0026rsquo;s a new version.\u0026#160;\u003ca href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli id=\"fn:2\"\u003e\n\u003cp\u003eIt also allowed downloading and installing Dart Sass, which I continue to do on a \u0026ldquo;just-in-case\u0026rdquo; basis even though I\u0026rsquo;ve kept the site almost exclusively on vanilla CSS, albeit enhanced with PostCSS for multi-browser compatibility purposes, for quite some time.\u0026#160;\u003ca href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli id=\"fn:3\"\u003e\n\u003cp\u003eI use the \u003ccode\u003ebaseURL\u003c/code\u003e flag because I like to test the site locally on multiple devices based on my LAN. The \u003ccode\u003eMY_IP\u003c/code\u003e variable provides the current local IP address of choice, which changes from time to time based on a variety of conditions.\u0026#160;\u003ca href=\"#fnref:3\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“My “new normal,” starting with Hugo 0.153.x”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"},{"title":"From Pages to Workers (again): revisited","date_published":"2025-11-24T14:44:00-06:00","id":"https://www.brycewray.com/posts/2025/11/pages-workers-again-revisited/","url":"https://www.brycewray.com/posts/2025/11/pages-workers-again-revisited/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"Getting the straight story from one who definitely knows what’s what at Cloudflare.","content_html":"\u003cem\u003eGetting the straight story from one who definitely knows what’s what at Cloudflare.\u003c/em\u003e\u003chr /\u003e\u003cp\u003eEarlier this year, I had \u003ca href=\"/posts/2025/05/pages-workers-again/\"\u003esome\u003c/a\u003e \u003ca href=\"/posts/2025/07/hugo-sites-cloudflare-workers-or-not/\"\u003ethings\u003c/a\u003e to say about a \u003ca href=\"https://blog.cloudflare.com/full-stack-development-on-cloudflare-workers/\" rel=\"noopener\"\u003eCloudflare announcement\u003c/a\u003e concerning its Cloudflare Workers (CFW) platform and, more to the points I was making, the Cloudflare Pages (CFP) product on which this site had lived for a good while. It now turns out that I may have misunderstood things at the time, so this post is my attempt to fix things somewhat.\u003c/p\u003e\n\u003cp\u003eMy concerns came from this statement, a few paragraphs down in the Cloudflare announcement:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eNow that Workers supports both serving static assets \u003cstrong\u003eand\u003c/strong\u003e server-side rendering, you should \u003cstrong\u003estart with Workers\u003c/strong\u003e. Cloudflare Pages will continue to be supported, but, going forward, all of our investment, optimizations, and feature work will be dedicated to improving Workers. We aim to make Workers the best platform for building full-stack apps, building upon your feedback of what went well with Pages and what we could improve. \u003cem\u003e[Emphases are Cloudflare\u0026rsquo;s.]\u003c/em\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eI considered this to be the announcement\u0026rsquo;s buried lede, and ended up summarizing it thusly:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eIn short: the CFP platform is now largely in maintenance mode, while its parent platform, CFW, is where Cloudflare will be investing its future dev efforts.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eAll that brings me to today, when I saw a \u003ca href=\"https://news.ycombinator.com/item?id=46034281\" rel=\"noopener\"\u003eHacker News thread\u003c/a\u003e about a \u003ca href=\"https://techlife.blog/posts/hugo-static-site-on-cloudflare/\" rel=\"noopener\"\u003eTechLife post\u003c/a\u003e concerning using Hugo with CFP. I added the following comment to the thread (the opening paragraph is a quote from one of my earlier posts on the subject):\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eIn an announcement [0] earlier this year, Cloudflare essentially put Cloudflare Pages on life support and began advising potential CFP users to build sites on the newly enhanced Cloudflare Workers platform instead.\u003c/p\u003e\n\u003cp\u003eI later wrote about this, particularly as it related to Hugo users.[1][2]\u003c/p\u003e\n\u003cp\u003e[0]: https://blog.cloudflare.com/full-stack-development-on-cloudflare-workers/\u003c/p\u003e\n\u003cp\u003e[1]: https://www.brycewray.com/posts/2025/05/pages-workers-again/\u003c/p\u003e\n\u003cp\u003e[2]: https://www.brycewray.com/posts/2025/07/hugo-sites-cloudflare-workers-or-not/\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eNot long thereafter, I saw that my comment had received a reply from none other than Cloudflare\u0026rsquo;s \u003ca href=\"https://github.com/kentonv\" rel=\"noopener\"\u003eKenton Varda\u003c/a\u003e:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThis is a bit of a misunderstanding.\u003c/p\u003e\n\u003cp\u003eWe are not sunsetting Pages. We are taking all the Pages-specific features and turning them into general Workers features -- which we should have done in the first place. At some point -- when we can do it with zero chance of breakage -- we will auto-migrate all Pages projects to this new implementation, essentially merging the platforms. We\u0026rsquo;re not ready to auto-migrate yet, but if you\u0026rsquo;re willing to do a little work you can manually migrate most Pages projects to Workers today. If you\u0026rsquo;d rather not, that\u0026rsquo;s fine, you can keep using Pages and wait for the auto-migration later.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eGiven his key role in the CFW project (as of this writing, he is its Tech Lead and has been for quite some time), that\u0026rsquo;s pretty much coming from the proverbial horse\u0026rsquo;s mouth!\u003c/p\u003e\n\u003cp\u003eI responded to thank him for the clarification, while also noting that I wish Cloudflare had run that key paragraph past him before sending me, and others, into subsequent confusion about its meaning:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e. . . which sounds (at least to me) more like an \u0026ldquo;either/or\u0026rdquo; situation, and a \u0026ldquo;Pages-is-going-into-maintenance mode\u0026rdquo; situation, than your answer suggests. But perhaps that\u0026rsquo;s just how I took it.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eFinally: I will continue to keep those two earlier posts on this site, only with notes pointing to this post \u0026mdash; not so much as a \u003cem\u003emea culpa\u003c/em\u003e or anything like that but, rather, just in the hope of providing a more complete look at the whole thing.\u003c/p\u003e\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“From Pages to Workers (again): revisited”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"},{"title":"Getting HTTP/3 on Cloudflare with Firefox","date_published":"2025-10-30T12:28:00-05:00","id":"https://www.brycewray.com/posts/2025/10/getting-http3-cloudflare-firefox/","url":"https://www.brycewray.com/posts/2025/10/getting-http3-cloudflare-firefox/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"There are two paths to the goal, although I can use only one.","content_html":"\u003cem\u003eThere are two paths to the goal, although I can use only one.\u003c/em\u003e\u003chr /\u003e\u003cp\u003eAfter wondering for a good while about a Firefox-specific weirdness I was seeing on Cloudflare-hosted sites, I finally found that there are two solutions. Only thing is, I am able to use only one of those two. That said, I\u0026rsquo;ll describe the problem and how I found the answers \u0026mdash; or, in my particular case, \u003cem\u003eanswer\u003c/em\u003e, singular.\u003c/p\u003e\n\u003cp class=\"box\"\u003e\u003cstrong\u003eNote\u003c/strong\u003e: I originally planned to have more content in this post, but a death occurred in my family during the editing process so I decided to keep this briefer. I hope what does follow will be sufficient for your understanding.\u003c/p\u003e\n\u003cp\u003eThe difficulty I encountered was that, on Firefox\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e, Cloudflare-hosted sites wouldn\u0026rsquo;t show up in \u003ca href=\"https://www.cloudflare.com/learning/performance/what-is-http3/\" rel=\"noopener\"\u003eHTTP/3\u003c/a\u003e, but instead fell back to HTTP/2. (You can test for yourself with the \u003ca href=\"https://cloudflare-quic.com/\" rel=\"noopener\"\u003eCloudflare test page\u003c/a\u003e for this type of connectivity.) I saw this on both macOS and Fedora Linux. While the performance penalty was likely tiny or nonexistent, it still bugged me and I wanted to find out what was causing this.\u003c/p\u003e\n\u003cp\u003eI filed a bug in Bugzilla but, if you do so without a Bugzilla account, that automatically generates an issue on the \u003ca href=\"https://github.com/webcompat\" rel=\"noopener\"\u003ewebcompat repo\u003c/a\u003e. Mine ended up \u003ca href=\"https://github.com/webcompat/web-bugs/issues/168913\" rel=\"noopener\"\u003ehere\u003c/a\u003e and, subsequently, resulted in \u003ca href=\"https://bugzilla.mozilla.org/show_bug.cgi?id=1979683\" rel=\"noopener\"\u003ethis Bugzilla issue\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eIn time, I learned this is related to something called the \u003ca href=\"https://everything.curl.dev/usingcurl/connections/happy.html\" rel=\"noopener\"\u003e\u0026ldquo;Happy Eyeballs\u0026rdquo; algorithm\u003c/a\u003e, Firefox\u0026rsquo;s handling of which has \u003ca href=\"https://bugzilla.mozilla.org/show_bug.cgi?id=1953459\" rel=\"noopener\"\u003eits own Bugzilla issue\u003c/a\u003e. It turned out that there are two remedies for the specific problem I\u0026rsquo;d seen. One is to use \u003ca href=\"https://www.cisco.com/site/us/en/learn/topics/networking/what-is-ipv6.html\" rel=\"noopener\"\u003eIPv6\u003c/a\u003e, and that\u0026rsquo;s a non-starter for me because my ISP doesn\u0026rsquo;t support IPv6. The other is to de-activate \u003ca href=\"https://support.mozilla.org/en-US/kb/firefox-dns-over-https\" rel=\"noopener\"\u003eDNS over HTTPS (DoH) in Firefox\u003c/a\u003e; once I did so, that freed up Firefox to \u0026ldquo;see\u0026rdquo; HTTP/3 on Cloudflare-hosted sites.\u003c/p\u003e\n\u003cdiv class=\"footnotes\" role=\"doc-endnotes\"\u003e\n\u003chr\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003eIncidentally, Safari often exhibits the same behavior if you have \u003ca href=\"https://support.apple.com/en-us/102602\" rel=\"noopener\"\u003eiCloud Private Relay\u003c/a\u003e activated. This appears to be \u003ca href=\"https://jedda.me/beneath-the-masque-network-relay-on-apple-platforms/\" rel=\"noopener\"\u003eintentional\u003c/a\u003e.\u0026#160;\u003ca href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\"\u003e\u0026#x21a9;\u0026#xfe0e;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“Getting HTTP/3 on Cloudflare with Firefox”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"}]}