{"id":24893,"date":"2026-08-22T23:47:13","date_gmt":"2026-08-23T03:47:13","guid":{"rendered":"https:\/\/nuxx.net\/blog\/?p=24893"},"modified":"2026-08-23T00:05:05","modified_gmt":"2026-08-23T04:05:05","slug":"chroma-syntax-highlighting-via-caddy","status":"publish","type":"post","link":"https:\/\/nuxx.net\/blog\/2026\/08\/22\/chroma-syntax-highlighting-via-caddy\/","title":{"rendered":"Chroma Syntax Highlighting via Caddy"},"content":{"rendered":"<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><a href=\"https:\/\/nuxx.net\/blog\/wp-content\/uploads\/2026\/08\/Screenshot-2026-08-22-at-23-15-31-seeed-xiao-esp32s3_onkyo-a-9050_v2.1.0.yaml-nuxx.net_.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"945\" src=\"https:\/\/nuxx.net\/blog\/wp-content\/uploads\/2026\/08\/Screenshot-2026-08-22-at-23-15-31-seeed-xiao-esp32s3_onkyo-a-9050_v2.1.0.yaml-nuxx.net_-1024x945.png\" alt=\"\" class=\"wp-image-24894\" srcset=\"https:\/\/nuxx.net\/blog\/wp-content\/uploads\/2026\/08\/Screenshot-2026-08-22-at-23-15-31-seeed-xiao-esp32s3_onkyo-a-9050_v2.1.0.yaml-nuxx.net_-1024x945.png 1024w, https:\/\/nuxx.net\/blog\/wp-content\/uploads\/2026\/08\/Screenshot-2026-08-22-at-23-15-31-seeed-xiao-esp32s3_onkyo-a-9050_v2.1.0.yaml-nuxx.net_-300x277.png 300w, https:\/\/nuxx.net\/blog\/wp-content\/uploads\/2026\/08\/Screenshot-2026-08-22-at-23-15-31-seeed-xiao-esp32s3_onkyo-a-9050_v2.1.0.yaml-nuxx.net_-768x708.png 768w, https:\/\/nuxx.net\/blog\/wp-content\/uploads\/2026\/08\/Screenshot-2026-08-22-at-23-15-31-seeed-xiao-esp32s3_onkyo-a-9050_v2.1.0.yaml-nuxx.net_-1536x1417.png 1536w, https:\/\/nuxx.net\/blog\/wp-content\/uploads\/2026\/08\/Screenshot-2026-08-22-at-23-15-31-seeed-xiao-esp32s3_onkyo-a-9050_v2.1.0.yaml-nuxx.net_.png 1778w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Chroma (via Caddy) highlighting ESPHome YAML.<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">After learning that <a href=\"https:\/\/github.com\/alecthomas\/chroma\">Chroma<\/a> is how <a href=\"https:\/\/caddyserver.com\/\">Caddy<\/a> renders <a href=\"https:\/\/en.wikipedia.org\/wiki\/Markdown\">Markdown<\/a> into HTML, I started thinking it&#8217;d be neat to use Chroma to do viewing with styling\/syntax highlighting of any supported files that I share\/archive at <a href=\"https:\/\/nuxx.net\/files\">nuxx.net\/files<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As I began investigating this, thinking that I&#8217;d have to do some sort of server-side rendering fed back to the webserver, it turned out there is a great hack that made it a lot simpler: Use the built-in Markdown support to render a code block (only) with the contents of each file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;m impressed with how this worked out. With some Caddyfile changes to call this, an updated custom file browser, and the HTML template (yes, all AI-assisted development &#8212; it came up with this hack) supported files in my archive get a nice VIEW button next to them which opens them in the viewer, or I can link directly to them with a <code>?viewer<\/code> argument. Adding an <code>hl=<\/code> argument will (eg: <code>hl=19<\/code> or <code>hl=10-15<\/code> or some comma-separated combination thereof) will highlight individual lines. The screenshot above is from this URL: <a href=\"https:\/\/nuxx.net\/files\/esphome\/seeed-xiao-esp32s3_onkyo-a-9050_v2.1.0.yaml?viewer&amp;hl=19\">https:\/\/nuxx.net\/files\/esphome\/seeed-xiao-esp32s3_onkyo-a-9050_v2.1.0.yaml?viewer&amp;hl=19<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This viewer is capped to 1MB files (larger just send the raw file as clicking\/direct linking do) and <code>hl<\/code> is limited to 100 characters, but this should suffice.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Oh yeah, so the how? Well, it&#8217;s all balled up with a whole bunch of CSS and site-specific stuff that I really don&#8217;t feel like stripping out to use as an example. And I don&#8217;t want an AI-generated how-to&#8230; so I guess all you get is the knowledge that this can be done and an example of it in practice. Hopefully that&#8217;s enough to feed to your agent and see how it can be implemented for you?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A bit of an aside, but as someone who remains quite skeptical of claims of what &#8220;AI&#8221; can do, I recognize and appreciate the power of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Large_language_model\">LLMs<\/a> for software development and troubleshooting. Being comfortable with such tools has made it much easier to get stuff done in my personal computer-hobby and day-job work time. Basically, I find that if I understand the inputs, the desired output (the goal), can describe the problem or task to be done, and can check things along the way, with a bit of guidance LLMs are great at filling in the time-sucking middle. This post from geohot really resonates with me and I suggest reading it the other posts\/articles it links to: <a href=\"https:\/\/geohot.github.io\/\/blog\/jekyll\/update\/2026\/07\/12\/i-love-llms.html\">I love LLMs, I hate hype<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After learning that Chroma is how Caddy renders Markdown into HTML, I started thinking it&#8217;d be neat to use Chroma to do viewing with styling\/syntax highlighting of any supported files that I share\/archive at nuxx.net\/files. As I began investigating this, thinking that I&#8217;d have to do some sort of server-side rendering fed back to the\u2026<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,4],"tags":[],"class_list":["post-24893","post","type-post","status-publish","format-standard","hentry","category-computers","category-nuxxnet"],"_links":{"self":[{"href":"https:\/\/nuxx.net\/blog\/wp-json\/wp\/v2\/posts\/24893","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nuxx.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nuxx.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nuxx.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nuxx.net\/blog\/wp-json\/wp\/v2\/comments?post=24893"}],"version-history":[{"count":7,"href":"https:\/\/nuxx.net\/blog\/wp-json\/wp\/v2\/posts\/24893\/revisions"}],"predecessor-version":[{"id":24905,"href":"https:\/\/nuxx.net\/blog\/wp-json\/wp\/v2\/posts\/24893\/revisions\/24905"}],"wp:attachment":[{"href":"https:\/\/nuxx.net\/blog\/wp-json\/wp\/v2\/media?parent=24893"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nuxx.net\/blog\/wp-json\/wp\/v2\/categories?post=24893"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nuxx.net\/blog\/wp-json\/wp\/v2\/tags?post=24893"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}