<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mondi</title>
    <description>The latest articles on DEV Community by Mondi (@mondi).</description>
    <link>https://dev.to/mondi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3945695%2Fe03a2aca-9f28-456a-8342-0fb81530f42f.png</url>
      <title>DEV Community: Mondi</title>
      <link>https://dev.to/mondi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mondi"/>
    <language>en</language>
    <item>
      <title>htmforge v0.4.0 released</title>
      <dc:creator>Mondi</dc:creator>
      <pubDate>Fri, 22 May 2026 09:34:49 +0000</pubDate>
      <link>https://dev.to/mondi/htmforge-v040-released-1cpg</link>
      <guid>https://dev.to/mondi/htmforge-v040-released-1cpg</guid>
      <description>&lt;h1&gt;
  
  
  v0.4.0
&lt;/h1&gt;

&lt;p&gt;One week out — here's what changed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Added
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Page.lang
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;Page&lt;/code&gt; component now accepts a &lt;code&gt;lang&lt;/code&gt; field that sets the&lt;br&gt;
&lt;code&gt;lang&lt;/code&gt; attribute on the &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_body_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;

&lt;span class="nc"&gt;MyPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Home&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;de&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_html&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;lt;!DOCTYPE html&amp;gt;&amp;lt;html lang="de"&amp;gt;...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Default is &lt;code&gt;"en"&lt;/code&gt;. Small thing, but accessibility tools and&lt;br&gt;
screen readers depend on it — it was an obvious gap.&lt;/p&gt;


&lt;h3&gt;
  
  
  Component.to_json()
&lt;/h3&gt;

&lt;p&gt;Useful for API endpoints that need to return rendered HTML&lt;br&gt;
alongside metadata:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UserCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ada&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# {"html": "&amp;lt;div class='card'&amp;gt;...", "component": "UserCard"}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Trusted Publishing
&lt;/h3&gt;

&lt;p&gt;Optional CI-based publish path via GitHub Actions —&lt;br&gt;
no local API token needed anymore.&lt;br&gt;
Documented in &lt;code&gt;docs/guide/trusted-publishing.md&lt;/code&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Changed
&lt;/h2&gt;
&lt;h3&gt;
  
  
  hatch-vcs
&lt;/h3&gt;

&lt;p&gt;Version is now sourced directly from git tags.&lt;br&gt;
No more manual version bumps in &lt;code&gt;pyproject.toml&lt;/code&gt; — &lt;br&gt;
tag the commit, the version follows automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[tool.hatch.version]&lt;/span&gt;
&lt;span class="py"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"vcs"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;release.py&lt;/code&gt; and &lt;code&gt;push.py&lt;/code&gt; now read the version&lt;br&gt;
from the git tag instead of &lt;code&gt;pyproject.toml&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fixed
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;README: all relative links replaced with absolute GitHub URLs
for correct rendering on PyPI&lt;/li&gt;
&lt;li&gt;DataTable docs updated — &lt;code&gt;ColumnDef&lt;/code&gt;, &lt;code&gt;dict_rows&lt;/code&gt;, &lt;code&gt;sort_url&lt;/code&gt;,
&lt;code&gt;current_sort&lt;/code&gt;, &lt;code&gt;sort_dir&lt;/code&gt;, &lt;code&gt;empty_message&lt;/code&gt; now fully documented&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docs/guide/components.md&lt;/code&gt;: broken code block fences and
garbled method names fixed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CONTRIBUTING.md&lt;/code&gt;: Good First Issues updated to reflect
actual open tasks&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; htmforge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 &lt;a href="https://github.com/mondi04/htmforge" rel="noopener noreferrer"&gt;github.com/mondi04/htmforge&lt;/a&gt;&lt;br&gt;&lt;br&gt;
👉 &lt;a href="https://github.com/mondi04/htmforge/releases/tag/v0.4.0" rel="noopener noreferrer"&gt;Full changelog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>htmx</category>
      <category>api</category>
      <category>fastapi</category>
    </item>
    <item>
      <title>Type-safe HTML in Python — no templates, no runtime surprises</title>
      <dc:creator>Mondi</dc:creator>
      <pubDate>Fri, 22 May 2026 09:04:21 +0000</pubDate>
      <link>https://dev.to/mondi/type-safe-html-in-python-no-templates-no-runtime-surprises-f1h</link>
      <guid>https://dev.to/mondi/type-safe-html-in-python-no-templates-no-runtime-surprises-f1h</guid>
      <description>&lt;h1&gt;
  
  
  Type-safe HTML in Python — no templates, no runtime surprises
&lt;/h1&gt;

&lt;p&gt;Been building FastAPI apps for a while.&lt;br&gt;
Every time the same thing: Jinja2 works until it doesn't.&lt;/p&gt;

&lt;p&gt;Misspelled variable? Silent empty cell. Missing context key? Crash on render.&lt;br&gt;
No mypy, no autocomplete, no safety net.&lt;/p&gt;

&lt;p&gt;I wanted something different, so I built htmforge —&lt;br&gt;
HTML entirely in Python, validated by Pydantic v2.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="c"&gt;{# users.html #}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;users&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;user.naem&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;{# typo — silent empty cell #}&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;user.role&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;{# wrong variant? find out at runtime #}&lt;/span&gt;
&lt;span class="cp"&gt;{%&lt;/span&gt; &lt;span class="k"&gt;endfor&lt;/span&gt; &lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  After
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;htmforge.components&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DataTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ColumnDef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BadgeVariant&lt;/span&gt;

&lt;span class="nc"&gt;DataTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;ColumnDef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;ColumnDef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;dict_rows&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Badge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="n"&gt;variant&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;BadgeVariant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DANGER&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;BadgeVariant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SUCCESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Typo in &lt;code&gt;"name"&lt;/code&gt;? Pydantic catches it on startup.&lt;br&gt;
Wrong &lt;code&gt;BadgeVariant&lt;/code&gt;? mypy catches it.&lt;br&gt;
XSS? Escaped automatically — no &lt;code&gt;| safe&lt;/code&gt; to misuse.&lt;/p&gt;




&lt;h2&gt;
  
  
  HTMX is typed too
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;htmforge.htmx&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HxSwap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HxTarget&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;htmforge.elements&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt;

&lt;span class="nf"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Delete&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;hx_delete&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/users/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;hx_swap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HxSwap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OUTER_HTML&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;hx_target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HxTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CLOSEST_TR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more &lt;code&gt;"outerHTML"&lt;/code&gt; string guessing. Full autocomplete.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pydantic v2&lt;/strong&gt; — prop validation on construction and assignment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MarkupSafe&lt;/strong&gt; — XSS protection, automatic, no opt-out&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;20+ components&lt;/strong&gt; — DataTable, Form, Modal, Toast, Tabs, Accordion...&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework adapters&lt;/strong&gt; — FastAPI, Flask, Django built in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;240 tests&lt;/strong&gt;, mypy strict, ruff clean&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Looking for contributors
&lt;/h2&gt;

&lt;p&gt;The project is early but functional. Good first issues are documented&lt;br&gt;
in &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; — from small things like adding a &lt;code&gt;lang&lt;/code&gt; attribute&lt;br&gt;
to &lt;code&gt;Page&lt;/code&gt;, to rendering improvements in &lt;code&gt;DataTable&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If this approach interests you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;👉 &lt;a href="https://github.com/mondi04/htmforge" rel="noopener noreferrer"&gt;github.com/mondi04/htmforge&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👉 &lt;code&gt;pip install htmforge&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>htmx</category>
      <category>webdev</category>
      <category>api</category>
    </item>
  </channel>
</rss>
