{"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":"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=\"(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=\"(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=\"(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=\"(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\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\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\u003e0.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\"\u003e0.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"},{"title":"Mixed nuts #16","date_published":"2025-09-26T12:12:00-05:00","id":"https://www.brycewray.com/posts/2025/09/mixed-nuts-16/","url":"https://www.brycewray.com/posts/2025/09/mixed-nuts-16/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"The Google ruling, Netlify’s pricing changes, and other tales of interest.","content_html":"\u003cem\u003eThe Google ruling, Netlify’s pricing changes, and other tales of interest.\u003c/em\u003e\u003chr /\u003e\u003cp\u003e\u003ca href=\"/posts/2025/06/mixed-nuts-15/\"\u003eYet again\u003c/a\u003e, I\u0026rsquo;ll indulge myself in commenting on a variety of topics stemming from the nerdy stuff to which I pay attention. I\u0026rsquo;d originally intended for this latest post to be focused on just one of them \u0026mdash; I\u0026rsquo;ll leave it to you to guess which \u0026mdash; but, the longer I procrastinated, the greater number of happenings that I wanted to discuss. It\u0026rsquo;s not a desirable habit, but it\u0026rsquo;s \u003cem\u003eMoi\u003c/em\u003e, folks. Let\u0026rsquo;s have at it.\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;ve spent most of this calendar year waiting to see what happened in the Google antitrust case. My expectation had been that we\u0026rsquo;d get a ruling in August, but it ended up slipping into early September. The most important effect of the ruling \u003ca href=\"https://ecf.dcd.uscourts.gov/cgi-bin/show_public_doc?2020cv3010-1436\" rel=\"noopener\"\u003e(PDF)\u003c/a\u003e, at least for us ordinary web-browsing folks out here, was that Alphabet\u0026rsquo;s Google arm gets to keep Chrome \u003cem\u003eand\u003c/em\u003e can keep paying organizations like Mozilla to promote the Google search engine. One can honestly and fairly debate the merits of both Google and Mozilla; but it\u0026rsquo;s a good thing that the incredibly important Chromium project will still have the nearly unlimited financial support that only Alphabet can give it, \u003cstrong\u003eand\u003c/strong\u003e it\u0026rsquo;s another good thing that there will still be financial backing for Mozilla\u0026rsquo;s Firefox browser (and, by extension, the numerous other FOSS projects that exist because Firefox\u0026rsquo;s Gecko engine can continue to exist). By the way, the ruling itself won\u0026rsquo;t go into effect for perhaps years due to the appellate process, but nearly all legal opinions I\u0026rsquo;ve seen on that particular aspect seem to agree that (what I consider to be) the good parts won\u0026rsquo;t change.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eStarting in mid-2020, \u003ca href=\"https://netlify.com\" rel=\"noopener\"\u003eNetlify\u003c/a\u003e\u0026rsquo;s free tier allowed 300 minutes per month of website deployments. I long ago \u003ca href=\"/posts/2020/06/o-say-can-you-ci-cd/\"\u003ewrote\u003c/a\u003e about how to get around this by using an external CI/CD provider, rather than Netlify\u0026rsquo;s servers, to build a Netlify-hosted  site. However, Netlify\u0026rsquo;s \u003ca href=\"https://www.netlify.com/blog/new-pricing-credits/\" rel=\"noopener\"\u003erecently announced overhaul to its pricing plans\u003c/a\u003e has changed that. Now, a project on the free plan gets 300\u003c/em\u003e \u003cem\u003e\u003cstrong\u003ecredits\u003c/strong\u003e\u003c/em\u003e \u003cem\u003eper month, and each deployment \u0026mdash; even if the build itself comes from elsewhere \u0026mdash; costs fifteen of those, meaning you get a maximum of twenty deploys a month on the free plan. This will be problematic for some and a nothing-burger for others. Just sayin\u0026rsquo;. And, in case you\u0026rsquo;re wondering: \u003ca href=\"https://docs.netlify.com/manage/accounts-and-billing/billing/billing-for-legacy-plans/billing-faq-for-legacy-plans/\" rel=\"noopener\"\u003eNetlify-hosted projects that were on the previous free plan prior to this change are grandfathered\u003c/a\u003e with the old 300-minute limit that\u0026rsquo;s unrelated to credits; but, going forward, the 300-credit free plan is the new normal.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThose who work with anything built on \u003ca href=\"https://www.npmjs.com/\" rel=\"noopener\"\u003enpm\u003c/a\u003e-hosted dependencies have been reminded and re-reminded in recent weeks that the resulting supply chain can, um, have its moments. \u003ca href=\"https://socket.dev/blog/ongoing-supply-chain-attack-targets-crowdstrike-npm-packages\" rel=\"noopener\"\u003eTwo different supply chain attacks\u003c/a\u003e using especially crafty social-engineering ploys briefly made the use of numerous popular dependencies problematic. GitHub (which, like npm, is owned by Microsoft) announced a \u003ca href=\"https://github.blog/security/supply-chain-security/our-plan-for-a-more-secure-npm-supply-chain/\" rel=\"noopener\"\u003eplan\u003c/a\u003e to improve the situation, but there inevitably will be ways of getting around even the \u003ca href=\"https://www.dictionary.com/browse/the-best-laid-plans-of-mice-and-men-often-go-awry\" rel=\"noopener\"\u003e\u0026ldquo;best laid\u0026rdquo; plans\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eApple released its latest major OS versions \u003ca href=\"https://www.apple.com/newsroom/2025/09/new-versions-of-apples-software-platforms-are-available-today/\" rel=\"noopener\"\u003eon September 15\u003c/a\u003e, and I have made peace with them for the most part. I am not a huge fan of the much-maligned \u003ca href=\"https://developer.apple.com/documentation/technologyoverviews/liquid-glass\" rel=\"noopener\"\u003eLiquid Glass\u003c/a\u003e look but, after tweaking things here and there, have managed to live with it without a whole lot of pain. Based on some of the videos I saw from the earliest betas of these OSs a few months ago, it could\u0026rsquo;ve been \u003ca href=\"https://finance.yahoo.com/news/ios-26-beta-3-dials-191254610.html\" rel=\"noopener\"\u003ea lot worse\u003c/a\u003e. And there are some new things I really like, such as being able to use a real Phone app on the Mac rather than an awkward interaction with the FaceTime app whenever I want to do an audio-only speakerphone call using my monitor\u0026rsquo;s audio system.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eI learned only this week of yet another Chromium-based browser in the wild, called \u003ca href=\"https://helium.computer\" rel=\"noopener\"\u003eHelium\u003c/a\u003e. It\u0026rsquo;s fully FOSS \u0026mdash; consider it a cooler, easier, and more updates-friendly way to use \u003ca href=\"https://github.com/ungoogled-software/ungoogled-chromium\" rel=\"noopener\"\u003eungoogled-chromium\u003c/a\u003e \u0026mdash; and is an attractive, lean, and quick performer. Helium is still in beta and the project has a few quirks that make it not yet ready for daily driving (at least mine), but it\u0026rsquo;s promising. If you can abide listening to \u003ca href=\"https://www.youtube.com/@t3dotgg\" rel=\"noopener\"\u003eTheo Browne\u003c/a\u003e on YouTube, \u003ca href=\"https://youtu.be/m1QrNF9wZao?t=3060\" rel=\"noopener\"\u003ethis link\u003c/a\u003e will take you to the relevant part of a browsers-comparison video where he discussed Helium and explained his confidence in those behind this project, to which he apparently donated some funding. Or, for an alternative take, you can also look at the (mostly negative and, I feel, often off-topic) comments in \u003ca href=\"https://news.ycombinator.com/item?id=45366867\" rel=\"noopener\"\u003ethis Hacker News thread\u003c/a\u003e.\u003c/p\u003e\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“Mixed nuts #16”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"},{"title":"New life for the old Mac with Linux: two years later","date_published":"2025-08-29T12:21:00-05:00","id":"https://www.brycewray.com/posts/2025/08/new-life-old-mac-linux-two-years-later/","url":"https://www.brycewray.com/posts/2025/08/new-life-old-mac-linux-two-years-later/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"Distro choices, uses, and a few continuing nits to pick.","content_html":"\u003cem\u003eDistro choices, uses, and a few continuing nits to pick.\u003c/em\u003e\u003chr /\u003e\u003cp\u003eTwo years have passed since I \u003ca href=\"/posts/2023/08/new-life-old-mac-linux/\"\u003ebegan telling you\u003c/a\u003e about putting Linux on the 2017 Intel iMac I\u0026rsquo;d recently shelved in favor of a \u003ca href=\"/posts/2023/07/making-good-move/\"\u003e2023 Apple Silicon Mac Studio\u003c/a\u003e. Apparently, some of the posts I wrote about this have become among my most frequently visited content, so here\u0026rsquo;s a brief update on how things are going with Linux on the older Mac.\u003c/p\u003e\n\u003cp\u003eMy distro-hopping of the early days \u0026mdash; mainly between Fedora and Arch \u0026mdash; settled on Fedora in late 2023, while I ran what turned out to be a \u003ca href=\"/posts/2023/12/testing-testing-ending-fools-errand/\"\u003eshort-lived\u003c/a\u003e project for testing web browsers. I found Fedora easier for that, because several browser-makers provide official versions for not only Red Hat-based distros like Fedora but also Debian-based distros; you need only \u003ca href=\"https://docs.fedoraproject.org/en-US/quick-docs/adding-or-removing-software-repositories-in-fedora/\" rel=\"noopener\"\u003eadd the appropriate repositories\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eEven after I ceased worrying about testing browsers, I still judged Fedora more convenient for the access to those official versions, not only for browsers but also other apps, such as 1Password. That remains true today. For other apps, I generally rely on either the official Fedora repository or \u003ca href=\"https://flathub.org/\" rel=\"noopener\"\u003eFlathub\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eI should add that I use \u0026ldquo;vanilla\u0026rdquo; Fedora Workstation. While I have tried \u003ca href=\"https://itsfoss.com/immutable-distro/\" rel=\"noopener\"\u003eimmutable distros\u003c/a\u003e, they felt a bit limiting in some ways. (To be fair, I\u0026rsquo;m sure that\u0026rsquo;s at least part of the intent for data-securing purposes, and it probably does work better for many folks.)\u003c/p\u003e\n\u003cp\u003eMy main use of Linux these days is as a gaming platform, thanks to the continuing advances of the \u003ca href=\"https://github.com/ValveSoftware/Proton\" rel=\"noopener\"\u003eProton\u003c/a\u003e project. However, I\u0026rsquo;ve also found a handy weather radar app, \u003ca href=\"https://github.com/dpaulat/supercell-wx\" rel=\"noopener\"\u003eSupercell Wx\u003c/a\u003e, which I can highly recommend.\u003c/p\u003e\n\u003cp\u003eI wish I could tell you I found solutions to some of the Linux-on-Mac issues I reported \u003ca href=\"/posts/2023/09/new-life-old-mac-linux-follow-up/\"\u003eback in 2023\u003c/a\u003e, but that\u0026rsquo;s not the case. Moreover, I suspect those solutions won\u0026rsquo;t be forthcoming for the reasons I outlined at that time. Specifically . . .\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eAudio\u003c/strong\u003e \u0026mdash; I never found a (permanent) way around the \u0026ldquo;dummy output\u0026rdquo; annoyance which made it impossible to use the iMac\u0026rsquo;s excellent built-in speaker system, so I\u0026rsquo;m still sticking to my workaround of USB-connected speakers. The sound quality isn\u0026rsquo;t great, but it\u0026rsquo;s also not terrible.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eVideo\u003c/strong\u003e \u0026mdash; The iMac\u0026rsquo;s Retina Display remains something Linux doesn\u0026rsquo;t know how to handle properly so, particularly given my gaming emphasis, I stick to plain old 1920 × 1080 resolution. Meh. At least the text is fairly clear, which wasn\u0026rsquo;t always the case when I was trying to use 2560 × 1440.\u003cbr\u003e\n(\u003cstrong\u003eUpdate/correction, 2025-08-30\u003c/strong\u003e: Well, I\u0026rsquo;d forgotten my actual settings. On rechecking, turns out I\u0026rsquo;m really using a setting of 3840 × 2160 but with text scaling set at 200%, \u003cstrong\u003ealthough\u003c/strong\u003e I run \u003cem\u003egames\u003c/em\u003e at 1920 × 1080 because, otherwise, the old Mac\u0026rsquo;s fans run a \u003cem\u003elot\u003c/em\u003e.)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSleep\u003c/strong\u003e \u0026mdash; Every once in a while, particularly after a major update to whatever distro I\u0026rsquo;m using at the time (\u003cem\u003ei.e.\u003c/em\u003e, this has been an ongoing practice for the last two years), I\u0026rsquo;ll play with system settings in an attempt to see if the iMac finally can sleep and be reawakened normally. Sadly, no joy yet. Although that\u0026rsquo;s a power-saving luxury I\u0026rsquo;d enjoyed all the years when the iMac was running macOS, it remains out of reach for Linux-on-Mac.\u003c/li\u003e\n\u003c/ul\u003e\n\u003chr\u003e\n\u003cp\u003eYou may have expected that I\u0026rsquo;d have more to report in this regard, but last year\u0026rsquo;s health problems kept me mostly off the old Mac for months at a time, so it\u0026rsquo;s really only this year that I have resumed any degree of truly active use of Linux on that device.\u003c/p\u003e\n\u003cp\u003eWhile the Apple Silicon Mac remains my daily driver, I fully anticipate continuing to use Linux on the Intel iMac as long as I\u0026rsquo;m able. Since Linux on Apple Silicon seems problematic for now and may remain so into the foreseeable future, I will inevitably have to decide what to do whenever Apple EOLs macOS for my newer Mac, just as it did in 2023 for the older one. On the other hand: since that event is likely several years out and I\u0026rsquo;m already about to turn seventy, will I even care by then? (Eyes, typing fingers, and brain cells tend to fail at some point. One can hold off Father Time only so long.) Perhaps I\u0026rsquo;ll find out someday.\u003c/p\u003e\u003cp\u003e\u003ca href=\"mailto:bw@brycewray.com?subject=“New life for the old Mac with Linux: two years later”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"},{"title":"Hugo sites on Cloudflare Workers — or not","date_published":"2025-07-11T13:46:00-05:00","id":"https://www.brycewray.com/posts/2025/07/hugo-sites-cloudflare-workers-or-not/","url":"https://www.brycewray.com/posts/2025/07/hugo-sites-cloudflare-workers-or-not/?utm_campaign=JSON&utm_source=JSON&utm_medium=JSON","authors":[{"name":"Bryce Wray"}],"summary":"Longer-term considerations about recently announced changes at Cloudflare.","content_html":"\u003cem\u003eLonger-term considerations about recently announced changes at Cloudflare.\u003c/em\u003e\u003chr /\u003e\u003cp class=\"box\"\u003e\u003cstrong\u003eNote\u003c/strong\u003e: After reading this, please see my \u003ca href=\"/posts/2025/11/pages-workers-again-revisited\"\u003elater post on this subject\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eOn further reflection, I\u0026rsquo;ve decided Cloudflare\u0026rsquo;s \u003ca href=\"https://blog.cloudflare.com/full-stack-development-on-cloudflare-workers/\" rel=\"noopener\"\u003equiet-ish announcement about the Cloudflare Pages platform\u003c/a\u003e, about which I first wrote \u003ca href=\"/posts/2025/05/pages-workers-again/\"\u003ea few weeks ago\u003c/a\u003e, bears some more discussion. That\u0026rsquo;s especially true for sites like this one, built on the \u003ca href=\"https://gohugo.io\" rel=\"noopener\"\u003eHugo\u003c/a\u003e static site generator (SSG).\u003c/p\u003e\n\u003cp\u003eIn fact, the whole thing has led me to think about how one might want to make a Hugo site more portable, to minimize the potential impact of such changes on vendors\u0026rsquo; parts both now and in the future. If you, too, have used Cloudflare Pages as a Hugo site\u0026rsquo;s home and are now pondering what to do, perhaps this post will help you understand your options more clearly.\u003c/p\u003e\n\u003ch2 id=\"our-story-so-far\"\u003e\u003ca class=\"header-anchor\" href=\"#our-story-so-far\"\u003eOur story so far . . .\u003c/a\u003e\u003c/h2\u003e\u003cp\u003eIn case you missed it: Cloudflare essentially put Cloudflare Pages (CFP) on life support a few months back, and began advising potential CFP users to build sites on the newly enhanced Cloudflare Workers (CFW) platform instead.\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e While the CFP platform will continue to exist at least for the time being, Cloudflare really wants folks to change over to CFW.\u003c/p\u003e\n\u003cp\u003eAnd, to be fair: this may not be that big a deal for sites built on JavaScript-based SSGs. Indeed, the CFW documentation includes a list of recommended site-building \u003ca href=\"https://developers.cloudflare.com/workers/framework-guides/web-apps/\" rel=\"noopener\"\u003eframeworks\u003c/a\u003e, each of which is a mass of JavaScript dependencies. As a result, for the most part, making CFW work with any of these frameworks can be as simple as \u003ccode\u003enpm install\u003c/code\u003e. That\u0026rsquo;s not the case with the Go-based Hugo, which is a binary.\u003c/p\u003e\n\u003cp\u003eWhen the CFP-to-CFW issue \u003ca href=\"https://discourse.gohugo.io/t/hugo-support-in-cloudflare-workers/54866\" rel=\"noopener\"\u003earose on the Hugo Discourse forum\u003c/a\u003e, \u003ca href=\"https://github.com/jmooring\" rel=\"noopener\"\u003eJoe Mooring\u003c/a\u003e of the Hugo project took time to provide \u003ca href=\"https://github.com/jmooring/hosting-cloudflare-worker\" rel=\"noopener\"\u003egreat guidance\u003c/a\u003e about putting a Hugo site on CFW. This made it easy enough to convert my own simple site from CFP to CFW the same day I found out about all this.\u003c/p\u003e\n\u003cp\u003eBut, in the ensuing weeks, I\u0026rsquo;ve seen online comments from Hugo users with more complex CFP-hosted sites and, unfortunately, ongoing issues trying to transition to CFW from the much easier CFP. For example, those whose sites depend on \u003ca href=\"https://git-scm.com/book/en/v2/Git-Tools-Submodules\" rel=\"noopener\"\u003eGit submodules\u003c/a\u003e, such as for externally produced \u003ca href=\"https://themes.gohugo.io/\" rel=\"noopener\"\u003ethemes\u003c/a\u003e, have found CFW currently unsuitable if used with a private repository.\u003csup id=\"fnref:2\"\u003e\u003ca href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e2\u003c/a\u003e\u003c/sup\u003e\u003c/p\u003e\n\u003cp\u003eThese users\u0026rsquo; frustrations are sufficient as to make them reconsider whether it\u0026rsquo;s worth even bothering with making the transition work \u003cem\u003evs.\u003c/em\u003e just starting over with a competing and, presumably, Hugo-friendlier (or less Hugo-unfriendly) host. Thoughts of this type inevitably lead one to wonder how to make one\u0026rsquo;s Hugo project as portable as possible, for just such cases.\u003csup id=\"fnref:3\"\u003e\u003ca href=\"#fn:3\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e3\u003c/a\u003e\u003c/sup\u003e\u003c/p\u003e\n\u003cp\u003eAfter much ensuing head-scratching and research in this vein, including even revisiting a few of my own past posts about the where-to-put-your-static-site issue, I reached some conclusions about how, and where, a Hugo-based site should exist  in the light of these new realities. As I walk you through some of my considerations, I hope they\u0026rsquo;ll help your own decision-making process if you\u0026rsquo;re entertaining similar contemplations.\u003c/p\u003e\n\u003ch2 id=\"binaries-are-the-biggie\"\u003e\u003ca class=\"header-anchor\" href=\"#binaries-are-the-biggie\"\u003eBinaries are the biggie\u003c/a\u003e\u003c/h2\u003e\u003cp\u003eFor a Hugo site, the first and foremost issue involves the handling of binaries.\u003c/p\u003e\n\u003cp\u003eBuilding with Hugo requires a host whose build image either \u003cem\u003ehas\u003c/em\u003e the Hugo binary or, at the very least, lets you install it during the build. Additionally: if you\u0026rsquo;re styling your site with \u003ca href=\"https://sass-lang.com\" rel=\"noopener\"\u003eSass\u003c/a\u003e, you must also be able to get the host to \u003ca href=\"https://gohugo.io/functions/css/sass/#dart-sass\" rel=\"noopener\"\u003einstall the Dart Sass binary into the correct path\u003c/a\u003e. (Even if you presently have no interest in using Sass on your Hugo site, you still may want your host at least to make it possible, just in case you change your mind later.)\u003c/p\u003e\n\u003cp\u003eWith the standard method of deploying to Cloudflare Pages \u0026mdash; namely, pushing a commit to a site\u0026rsquo;s connected Git repository \u0026mdash; a Hugo site owner could, with relative ease:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eSpecify the Hugo version (one was included in the CFP build image, but I personally prefer to pick the version myself).\u003c/li\u003e\n\u003cli\u003eUse the Dart Sass binary \u003cstrong\u003eand\u003c/strong\u003e specify the version.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eOn the other hand: the \u003ca href=\"https://developers.cloudflare.com/workers/ci-cd/builds/build-image/\" rel=\"noopener\"\u003eCloudflare Workers build image\u003c/a\u003e offers a pre-selected Hugo binary, perhaps not the latest, and doesn\u0026rsquo;t allow you to pick a version.\u003csup id=\"fnref:4\"\u003e\u003ca href=\"#fn:4\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e4\u003c/a\u003e\u003c/sup\u003e Moreover, the CFW build image doesn\u0026rsquo;t offer Dart Sass at all. Of course, the latter isn\u0026rsquo;t terribly surprising since, again, Cloudflare expects most SSG users to be running JS-based SSGs, and those usually work with Sass through some interaction with the \u003ca href=\"https://github.com/sass/sass\" rel=\"noopener\"\u003eSass package\u003c/a\u003e\u003csup id=\"fnref:5\"\u003e\u003ca href=\"#fn:5\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e5\u003c/a\u003e\u003c/sup\u003e rather than the \u003ca href=\"https://github.com/sass/dart-sass\" rel=\"noopener\"\u003eDart Sass binary\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eWhat about the competition? Here\u0026rsquo;s how the only competing hosts I\u0026rsquo;ll mention\u003csup id=\"fnref:6\"\u003e\u003ca href=\"#fn:6\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e6\u003c/a\u003e\u003c/sup\u003e fare in this regard:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eHugo\u003c/strong\u003e \u0026mdash; The build images for \u003ca href=\"https://www.netlify.com\" rel=\"noopener\"\u003eNetlify\u003c/a\u003e, \u003ca href=\"https://render.com\" rel=\"noopener\"\u003eRender\u003c/a\u003e, and \u003ca href=\"https://vercel.com\" rel=\"noopener\"\u003eVercel\u003c/a\u003e provide Hugo and let you specify the version. Netlify and Vercel give you two ways to specify the \u003ccode\u003eHUGO_VERSION\u003c/code\u003e environment variable: through the GUI, or in a config file \u0026mdash; \u003ccode\u003enetlify.toml\u003c/code\u003e or \u003ccode\u003evercel.json\u003c/code\u003e, respectively. With Render, the only way to set the Hugo version is with a \u003ca href=\"https://community.render.com/t/how-to-define-hugo-version/390/7\" rel=\"noopener\"\u003eshell script\u003c/a\u003e; otherwise, as of this writing, you get a Hugo version from multiple years ago.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDart Sass\u003c/strong\u003e \u0026mdash; With Netlify, you can get the Dart Sass binary and specify its version \u003ca href=\"https://gohugo.io/functions/css/sass/#netlify\" rel=\"noopener\"\u003ethrough scripting in \u003ccode\u003enetlify.toml\u003c/code\u003e\u003c/a\u003e, but not through the Netlify GUI. As for Render and Vercel, I know a \u003ca href=\"https://discourse.gohugo.io/t/using-dart-sass-hugo-and-netlify/37099/7\" rel=\"noopener\"\u003eshell script\u003c/a\u003e suggested by Hugo\u0026rsquo;s \u003ca href=\"https://github.com/bep\" rel=\"noopener\"\u003eBjørn Erik Pedersen\u003c/a\u003e worked \u003ca href=\"/posts/2022/03/using-dart-sass-hugo-sequel/\"\u003eat one time\u003c/a\u003e, but I haven\u0026rsquo;t tried it on either host recently.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe bottom line on these binaries and the three hosts\u0026rsquo; native deployment environments is: you can spec your chosen Hugo binary on all three hosts (although not so easily with Render), but using and spec\u0026rsquo;g the Dart Sass binary is safest with Netlify.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHowever\u003c/strong\u003e, in my experience, it\u0026rsquo;s easier for a Hugo user to solve the whole problem with \u003cem\u003eany\u003c/em\u003e of these hosts by using a \u003cstrong\u003eseparate CI/CD provider\u003c/strong\u003e, either \u003ca href=\"https://github.com/features/actions\" rel=\"noopener\"\u003eGitHub Actions\u003c/a\u003e or \u003ca href=\"https://about.gitlab.com/solutions/continuous-integration/\" rel=\"noopener\"\u003eGitLab CI/CD\u003c/a\u003e. This \u003cstrong\u003ehost-agnostic\u003c/strong\u003e approach gives you much more control over which binaries you download, which versions you get, and other factors that are important for Hugo users.\u003csup id=\"fnref:7\"\u003e\u003ca href=\"#fn:7\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e7\u003c/a\u003e\u003c/sup\u003e Although explaining the process is beyond this post\u0026rsquo;s scope (if needed, refer to the Hugo \u003ca href=\"https://gohugo.io/host-and-deploy/\" rel=\"noopener\"\u003e\u0026ldquo;Host and deploy\u0026rdquo; docs\u003c/a\u003e), suffice it to say that each host I\u0026rsquo;ve discussed here allows building sites through both GitHub Actions and GitLab CI/CD.\u003csup id=\"fnref:8\"\u003e\u003ca href=\"#fn:8\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e8\u003c/a\u003e\u003c/sup\u003e\u003c/p\u003e\n\u003cp class=\"box\"\u003e\u003cstrong\u003eNote\u003c/strong\u003e: To be fair, I remind you of my \u003ca href=\"/posts/2022/07/using-dart-sass-hugo-some-data-using-github-actions/\"\u003e2022 findings\u003c/a\u003e concerning potential issues in using GitHub Actions with a Vercel-hosted Hugo site in which Hugo\u0026rsquo;s native image-processing functionality is in use. However, I haven\u0026rsquo;t tested sufficiently to know if the problem still exists, and that was three whole years ago; so I suspect (hope?) that, since, there have been plenty of improvements to the infrastructure that even Vercel\u0026rsquo;s free tier uses.\u003c/p\u003e\n\u003ch2 id=\"one-heretical-afterthought-to-consider\"\u003e\u003ca class=\"header-anchor\" href=\"#one-heretical-afterthought-to-consider\"\u003eOne heretical afterthought to consider\u003c/a\u003e\u003c/h2\u003e\u003cp\u003eBefore I press on to the finish, I\u0026rsquo;ll dwell briefly on what may be the elephant in this discussion\u0026rsquo;s room: the choice of SSG itself.\u003c/p\u003e\n\u003cp\u003eAs noted, Cloudflare\u0026rsquo;s recent changes are potentially much more of a hassle for Hugo users than for those using JavaScript-based SSGs. But, as you probably already knew, Cloudflare isn\u0026rsquo;t alone in this respect. Indeed, most hosting platforms clearly favor the JS-based tools which have long constituted the overwhelming majority of site-building products; and this favoritism likely will only grow over time.\u003c/p\u003e\n\u003cp\u003eSo, is it time for you, a Hugo user, to throw in the towel and jump ship to a different, JS-based SSG? Will that make your site more future-proof?\u003c/p\u003e\n\u003cp\u003eWell, only you can make that call. If you do switch, I can tell you from my years of experience that the Hugo-to-whatever conversion process will be anywhere from fairly easy to excruciating, depending largely on two factors: (a.) how big your site is; and (b.) how much Hugo-specific customization your site has. Mine has several hundred pages and more than a little Hugo-ish code that would be a bear to translate, so this site isn\u0026rsquo;t a likely candidate for now.\u003c/p\u003e\n\u003cp\u003eThat said, my long-time readers know I have strayed from the Hugo ranch numerous times in the site\u0026rsquo;s nearly seven years of existence, so I can offer a little more specific advice on the subject of possibly switching from Hugo to something else.\u003c/p\u003e\n\u003cp\u003eOf the JS-based SSGs I\u0026rsquo;ve used over the years to build this site whenever it wasn\u0026rsquo;t a Hugo project, the only SSG that\u0026rsquo;s on Cloudflare\u0026rsquo;s aforementioned list of recommended platforms is \u003ca href=\"https://astro.build\" rel=\"noopener\"\u003eAstro\u003c/a\u003e; and, mind you, my time on Astro was miniscule compared to the many months I used \u003ca href=\"https://www.11ty.dev\" rel=\"noopener\"\u003eEleventy\u003c/a\u003e. (I also used the now largely moribund Gatsby, and even it gets a little love in the current Cloudflare Workers documentation \u0026mdash; in fact, more than for Eleventy, much less Hugo.) Even when just tinkering, I haven\u0026rsquo;t used either Astro or Eleventy extensively in a couple of years; but I feel either is a solid alternative as a site-building platform to which the typical JS-favoring host is at least less averse than it is to Hugo.\u003csup id=\"fnref:9\"\u003e\u003ca href=\"#fn:9\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e9\u003c/a\u003e\u003c/sup\u003e\u003c/p\u003e\n\u003ch2 id=\"so-where\"\u003e\u003ca class=\"header-anchor\" href=\"#so-where\"\u003eSo, where?\u003c/a\u003e\u003c/h2\u003e\u003cp\u003eAll right, let\u0026rsquo;s get to the bottom line. After I\u0026rsquo;d given all this thought to how I could make my own Hugo site more portable and thus less vulnerable to the whims of different hosts, what did I end up doing about the site\u0026rsquo;s hosting?\u003c/p\u003e\n\u003cp\u003eIn fact, I did nothing. As of this post\u0026rsquo;s initial publication, the site is still on Cloudflare Workers.  It all still works, after all. \u003cstrong\u003eBut\u003c/strong\u003e, now, I know how to make a quick exit if I do choose. It\u0026rsquo;s my hope that what I\u0026rsquo;ve shared in this post will give you similar knowledge.\u003c/p\u003e\n\u003cp\u003eBut where \u003cstrong\u003ewould\u003c/strong\u003e I go if I \u003cstrong\u003edon\u0026rsquo;t\u003c/strong\u003e stay with CFW? It would be between Netlify and Vercel. (While I admire Render as a company, I\u0026rsquo;m not as comfortable with configuring for it, especially where Hugo-specific things are concerned, as I am with the other two.) If I had to pick a winner, it would come down to how wedded I\u0026rsquo;d be to using external CI/CD, as I now do with the CFW site and did with its CFP predecessor. That\u0026rsquo;s because, in my testing, I found external CI/CD somewhat easier with Vercel than with Netlify, while Netlify\u0026rsquo;s native GUI provides better support for Hugo than does Vercel\u0026rsquo;s. So it really would come down to whether I\u0026rsquo;d prefer external CI/CD. If yes, it would be Vercel. If no, it would be Netlify.\u003csup id=\"fnref:10\"\u003e\u003ca href=\"#fn:10\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e10\u003c/a\u003e\u003c/sup\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\u003eYeah, I know: CFP is, and has always been, built atop CFW anyway; but you get the idea.\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\u003eOn June 23, a commenter on the Cloudflare Developers Discord \u003ca href=\"https://discord.com/channels/595317990191398933/1384675816935264387/1386742596864446498\" rel=\"noopener\"\u003esaid\u003c/a\u003e, \u0026ldquo;Did a little bit of checking, looks like ssh urls in submodules are not currently supported[.]\u0026rdquo; Seeing a reference to this, someone on the unofficial Hugo Discord observed, \u0026ldquo;\u003ca href=\"https://discord.com/channels/909600839717511208/986390889792438344/1388171002881773619\" rel=\"noopener\"\u003eso if u have a private repository, the URL alone wouldn\u0026rsquo;t allow CF to read the repository\u003c/a\u003e.\u0026rdquo;\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\u003eTo quote \u003ca href=\"https://www.youtube.com/watch?v=S9dF5xuJBbM\" rel=\"noopener\"\u003eFoghorn Leghorn\u003c/a\u003e: \u0026ldquo;Fortunately, I keep my feathers numbered for just such an emergency.\u0026rdquo;\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\u003cli id=\"fn:4\"\u003e\n\u003cp\u003e\u003cstrong\u003eUpdate, 2025-07-18\u003c/strong\u003e: I later learned, via Discord, from a fellow Hugo user that you actually can select the Hugo version with the Workers build image, in the same way as you would\u0026rsquo;ve with Pages \u0026mdash; \u003cem\u003ei.e.\u003c/em\u003e, through use of a \u003ccode\u003eHUGO_VERSION\u003c/code\u003e environment variable. It\u0026rsquo;s just \u003ca href=\"https://developers.cloudflare.com/workers/ci-cd/builds/build-image/#overriding-default-versions\" rel=\"noopener\"\u003enot clearly documented\u003c/a\u003e. I don\u0026rsquo;t know whether a similar capability exists for using a \u003ccode\u003eDART_SASS_VERSION\u003c/code\u003e environment variable to get the Dart Sass binary; the \u003ccode\u003eHUGO_VERSION\u003c/code\u003e trick likely works because there already is a Hugo binary in the Workers build image, but the same doesn\u0026rsquo;t appear to be true for a Dart Sass binary.\u0026#160;\u003ca href=\"#fnref:4\" 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:5\"\u003e\n\u003cp\u003eIncidentally, another exception involves someone using Sass with the Rust-based \u003ca href=\"https://www.getzola.org\" rel=\"noopener\"\u003eZola\u003c/a\u003e SSG. Zola uses the Rust \u003ca href=\"https://crates.io/crates/grass\" rel=\"noopener\"\u003e\u003ccode\u003egrass\u003c/code\u003e crate\u003c/a\u003e for a \u0026ldquo;more-or-less\u0026rdquo;-ish compatibility with Dart Sass. I say \u0026ldquo;\u0026lsquo;more-or-less\u0026rsquo;-ish\u0026rdquo; because the latest release of \u003ccode\u003egrass\u003c/code\u003e, at least as of this post\u0026rsquo;s initial appearance, is lagging quite a bit behind that of the official Dart Sass binary. Whether that matters much is up to each Sass-using Zola site owner; but, were I that user, I wouldn\u0026rsquo;t like it very much, especially given the fairly active cadence of Dart Sass updates. Also on the subject of Zola: currently, its binary isn\u0026rsquo;t in the CFW build image.\u0026#160;\u003ca href=\"#fnref:5\" 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:6\"\u003e\n\u003cp\u003eA quick review of the free tier of Digital Ocean\u0026rsquo;s Apps Platform shows that DOAP remains as unsuitable as I found it in \u003ca href=\"/posts/2023/03/publish-or-perish-2023/#digitalocean-app-platform\"\u003e2023\u003c/a\u003e, thus deserving no real mention in any comparisons herein.\u0026#160;\u003ca href=\"#fnref:6\" 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:7\"\u003e\n\u003cp\u003eOne notable example is if you like to use \u003ca href=\"https://gohugo.io/methods/page/gitinfo/\" rel=\"noopener\"\u003eGit Info variables\u003c/a\u003e. Most hosts\u0026rsquo; \u0026ldquo;native\u0026rdquo; methods \u003ca href=\"https://gohugo.io/methods/page/gitinfo/#hosting-considerations\" rel=\"noopener\"\u003edon\u0026rsquo;t make that very easy\u003c/a\u003e.\u0026#160;\u003ca href=\"#fnref:7\" 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:8\"\u003e\n\u003cp\u003eBe aware that, if you do the Hugo build process on the CI/CD provider, you\u0026rsquo;ll need to experiment with the correct location of the respective config file. For example, it may need to be in your Hugo directory\u0026rsquo;s \u003ccode\u003e/static\u003c/code\u003e directory rather than the usual location (the root directory), but my own tests showed me this isn\u0026rsquo;t always true \u003cstrong\u003eand\u003c/strong\u003e can vary according to the specific workflow code you\u0026rsquo;re using to deploy the site from within the CI/CD provider. Again, \u003cem\u003eexperiment\u003c/em\u003e. Failure to put the file in the correct location means that, when the CI/CD provider turns the process over to Netlify, Render, or Vercel, the latter won\u0026rsquo;t \u0026ldquo;see\u0026rdquo; the config file and the build likely will error out rather than proceeding.\u0026#160;\u003ca href=\"#fnref:8\" 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:9\"\u003e\n\u003cp\u003eA few days ago, long-time Hugo user \u003ca href=\"https://github.com/davidsneighbour\" rel=\"noopener\"\u003ePatrick Kollitsch\u003c/a\u003e converted \u003ca href=\"https://kollitsch.dev\" rel=\"noopener\"\u003ehis website\u003c/a\u003e to Astro. Please note that he is an \u003cem\u003eextremely\u003c/em\u003e knowledgeable coder, as one look at his \u003ca href=\"https://github.com/davidsneighbour/kollitsch.dev\" rel=\"noopener\"\u003esite repository\u003c/a\u003e will make clear, so his switch isn\u0026rsquo;t necessarily a guide for all; but his site is a large one with several years\u0026rsquo; worth of content, so I salute the effort he undertook to make the change.\u0026#160;\u003ca href=\"#fnref:9\" 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:10\"\u003e\n\u003cp\u003eStill, with a site that regularly needs a lot of changes, one would be better off using external CI/CD with Netlify to circumvent the Netlify free tier\u0026rsquo;s monthly build limits. I wrote about this very thing \u003ca href=\"/posts/2020/06/o-say-can-you-ci-cd/\"\u003efive years ago\u003c/a\u003e and the situation hasn\u0026rsquo;t changed.\u0026#160;\u003ca href=\"#fnref:10\" 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 sites on Cloudflare Workers — or not”\"\u003eReply via email\u003c/a\u003e\u003c/p\u003e"}]}