<?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: YOUNESS MOJAHID</title>
    <description>The latest articles on DEV Community by YOUNESS MOJAHID (@mojahid0youness).</description>
    <link>https://dev.to/mojahid0youness</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3892858%2F9e9d1d66-8c09-4305-a33b-371aa0306bc4.jpeg</url>
      <title>DEV Community: YOUNESS MOJAHID</title>
      <link>https://dev.to/mojahid0youness</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mojahid0youness"/>
    <language>en</language>
    <item>
      <title>Introduction to Probo-ui — Write HTML Entirely in Python series</title>
      <dc:creator>YOUNESS MOJAHID</dc:creator>
      <pubDate>Fri, 17 Jul 2026 09:40:42 +0000</pubDate>
      <link>https://dev.to/mojahid0youness/introduction-to-probo-ui-write-html-entirely-in-python-series-5185</link>
      <guid>https://dev.to/mojahid0youness/introduction-to-probo-ui-write-html-entirely-in-python-series-5185</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A tutorial series, DEV.to blog series — from your first HTML element to production-grade User Interfaces, all in pure Python.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Modern Python web frameworks force developers into a split workflow: business logic lives in Python files with full IDE support, while presentation logic is exiled to template files that offer none of it. Template languages like Jinja2 introduce their own syntax for conditionals, loops, and variable access — syntax that your linter cannot check, your type checker cannot verify, and your debugger cannot step through. Every context variable passed across that boundary is a potential KeyError waiting to surface at runtime. Probo eliminates this divide entirely by making HTML a native Python construct — written, validated, and refactored with the same tools you already use for the rest of your codebase.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  PART 1: Introduction to Probo — Write HTML Entirely in Python
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is Probo?
&lt;/h3&gt;

&lt;p&gt;Probo is a &lt;strong&gt;Python-first, declarative UI rendering framework&lt;/strong&gt;. Instead of writing HTML in &lt;code&gt;.html&lt;/code&gt; files or using template languages like Jinja2, you write &lt;em&gt;everything&lt;/em&gt; in pure Python.&lt;/p&gt;

&lt;p&gt;No template files. No string concatenation. No f-strings full of angle brackets. Just Python functions and classes that &lt;strong&gt;are&lt;/strong&gt; your HTML.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Two Flavors of Every Tag
&lt;/h3&gt;

&lt;p&gt;Every HTML tag in Probo comes in two forms:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flavor&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Returns&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Function&lt;/strong&gt; (lowercase)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;div()&lt;/code&gt;, &lt;code&gt;h1()&lt;/code&gt;, &lt;code&gt;p()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Rendered HTML&lt;/td&gt;
&lt;td&gt;Quick rendering, lightweight&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Class&lt;/strong&gt; (uppercase)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;DIV()&lt;/code&gt;, &lt;code&gt;H1()&lt;/code&gt;, &lt;code&gt;P()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;SSDOM tree node&lt;/td&gt;
&lt;td&gt;Tree manipulation, streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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;probo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DIV&lt;/span&gt;

&lt;span class="c1"&gt;# Function: returns a string immediately
# return_list=True
&lt;/span&gt;&lt;span class="n"&gt;html_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;div&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 World&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
&lt;span class="c1"&gt;# → "&amp;lt;div&amp;gt;Hello World&amp;lt;/div&amp;gt;"
&lt;/span&gt;
&lt;span class="c1"&gt;# Class: returns a tree node, call .render() to get the string
&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DIV&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 World&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main-title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Because it's a Node, you can manipulate it dynamically
&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Subtitle added later!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;html_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# → '&amp;lt;div id="main-title"&amp;gt;Hello World&amp;lt;div&amp;gt;Subtitle added later!&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: &lt;em&gt;by adding return_deque=True or return_list=True the output changes from string to respective return type&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Built-in Security
&lt;/h3&gt;

&lt;p&gt;Probo auto-escapes all text content by default via &lt;code&gt;markup_escape&lt;/code&gt;. If a user submits &lt;code&gt;&amp;lt;script&amp;gt;alert('xss')&amp;lt;/script&amp;gt;&lt;/code&gt;, Probo renders it as harmless escaped text — no XSS vulnerabilities out of the box.&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;probo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;

&lt;span class="c1"&gt;# User-submitted content is automatically escaped
&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;script&amp;gt;alert(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hacked&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;)&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;safe_html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;p&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# → "&amp;lt;p&amp;gt;&amp;amp;lt;script&amp;amp;gt;alert(&amp;amp;quot;hacked&amp;amp;quot;)&amp;amp;lt;/script&amp;amp;gt;&amp;lt;/p&amp;gt;"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What You'll Learn in This Series
&lt;/h3&gt;

&lt;p&gt;By the end of this series, you'll be able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build full HTML pages in Python&lt;/li&gt;
&lt;li&gt;Navigate and manipulate a server-side DOM tree&lt;/li&gt;
&lt;li&gt;Bind dynamic data without prop-drilling&lt;/li&gt;
&lt;li&gt;Run a web server with routing, caching, and streaming&lt;/li&gt;
&lt;li&gt;Build interactive UIs with HTMX — with minimal to no JavaScript required&lt;/li&gt;
&lt;li&gt;Create reusable, skinnable component systems&lt;/li&gt;
&lt;li&gt;Deploy with Gunicorn or Uvicorn&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started! 👇&lt;/p&gt;

</description>
      <category>python</category>
      <category>webdev</category>
      <category>html</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>If Your Backend Is Python, Why Isn’t Your UI? — Probo-UI 1.4.0</title>
      <dc:creator>YOUNESS MOJAHID</dc:creator>
      <pubDate>Wed, 22 Apr 2026 21:09:11 +0000</pubDate>
      <link>https://dev.to/mojahid0youness/if-your-backend-is-python-why-isnt-your-ui-probo-ui-140-53co</link>
      <guid>https://dev.to/mojahid0youness/if-your-backend-is-python-why-isnt-your-ui-probo-ui-140-53co</guid>
      <description>&lt;p&gt;I got tired of this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write logic in &lt;code&gt;views.py&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Jump to HTML&lt;/li&gt;
&lt;li&gt;Add a condition&lt;/li&gt;
&lt;li&gt;Go back to Python&lt;/li&gt;
&lt;li&gt;Repeat 50 times&lt;/li&gt;
&lt;li&gt;And if a template has a layout issue… good luck finding the element&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At some point it clicked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Templates aren’t UI. They’re just strings with logic inside.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I built &lt;strong&gt;Probo UI&lt;/strong&gt; — now in a stable 1.4.0 version where UI is no longer text…&lt;/p&gt;

&lt;p&gt;It’s &lt;strong&gt;Python objects you can edit, reuse, and compose&lt;/strong&gt; — literally what Probo stands for:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Python Rendered Objects for Backend-Oriented User Interfaces&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Idea in One Line
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;UI = Python object tree (SSDOM), not static HTML&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Probo turns UI into a &lt;strong&gt;mutable structure&lt;/strong&gt;, not a final string.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Write UI Like This (Not Templates)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Example 1 — Basic Component
&lt;/h3&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;probo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DIV&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;profile_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;DIV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;P&lt;/span&gt;&lt;span class="p"&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;Role: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;role&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;Class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;profile-card&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;profile_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Youness&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;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No template file. No &lt;code&gt;{% %}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Just Python.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Now Mutate It (This Is the Shift)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Example 2 — Dynamic Styling (No Template Rewrite)
&lt;/h3&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="nf"&gt;profile_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Youness&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;admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;user_status&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="n"&gt;attr_manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin-border&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="n"&gt;style_manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;red&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;style_manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;margin_top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;50px&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;print&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;render&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You didn’t:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;duplicate templates&lt;/li&gt;
&lt;li&gt;add &lt;code&gt;{% if %}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;inject class strings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You just &lt;strong&gt;modified the object&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Build Real Components (Reusable Blocks)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Example 3 — Real Component with Data
&lt;/h3&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;probo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;li&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strong&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user_id&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;User_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;skills&lt;/span&gt; &lt;span class="o"&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;python&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;django&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;docker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return&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="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;strong&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="nf"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;li&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&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;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;skills&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;card&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not “template rendering”.&lt;/p&gt;

&lt;p&gt;This is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;component composition in Python&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  4. Permission-Based UI (No Template Logic Hell)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Example 4 — Conditional Rendering (Built-in)
&lt;/h3&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;probo.components&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ComponentState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StateProps&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;probo&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ul&lt;/span&gt;  &lt;span class="c1"&gt;# functional tags (not OOP)
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;user_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StateProps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prop_equal_to&lt;/span&gt;&lt;span class="o"&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;username&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;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;data&lt;/span&gt; &lt;span class="o"&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;skills&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;python&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;django&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;

    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ComponentState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Component&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;UserCard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&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;ul&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
        &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&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;username&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;user_card&lt;/span&gt;&lt;span class="p"&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="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;   &lt;span class="c1"&gt;# empty
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;user_card&lt;/span&gt;&lt;span class="p"&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="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;   &lt;span class="c1"&gt;# shows data
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;{% if user.is_admin %}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;scattered logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;structured, state-driven UI&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  5. Live Demo — Multi-Role UI (Customer / Staff / Admin) + HTMX
&lt;/h2&gt;

&lt;p&gt;👉 &lt;a href="https://youness00mojahid.pythonanywhere.com/" rel="noopener noreferrer"&gt;https://youness00mojahid.pythonanywhere.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a &lt;strong&gt;real app built with Probo UI + Django + HTMX&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It demonstrates how one system can generate &lt;strong&gt;multiple interfaces from the same components&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧑‍💻 Customer UI
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Clean product/service views&lt;/li&gt;
&lt;li&gt;Minimal controls&lt;/li&gt;
&lt;li&gt;Limited interaction&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Same components — just rendered with different state.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🧑‍🔧 Staff UI
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Edit/manage controls appear&lt;/li&gt;
&lt;li&gt;More data becomes visible&lt;/li&gt;
&lt;li&gt;Components extend behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;No new templates — just &lt;strong&gt;mutated components&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🛠️ Admin UI
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Full control panels&lt;/li&gt;
&lt;li&gt;Management actions&lt;/li&gt;
&lt;li&gt;Expanded UI&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Same base UI — dynamically transformed.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  ⚡ Dynamic Interactions (HTMX)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No full page reloads&lt;/li&gt;
&lt;li&gt;Server-rendered partial updates&lt;/li&gt;
&lt;li&gt;Lightweight interactivity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Workflow:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Python = structure + logic&lt;br&gt;
HTMX = interaction&lt;br&gt;
Browser = render&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🧠 What This Demo Proves
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;One UI system → multiple roles&lt;/li&gt;
&lt;li&gt;No template duplication&lt;/li&gt;
&lt;li&gt;Dynamic UI without frontend frameworks&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  💡 The Key Takeaway
&lt;/h3&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;customer.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;staff.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;admin.html&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You build:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;one UI system that adapts itself&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  6. The Core Concept (Short Version)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SSDOM (Server-Side DOM):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI is a &lt;strong&gt;Python tree&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;You can &lt;strong&gt;modify it before rendering&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;HTML is just output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This avoids:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;template fragmentation&lt;/li&gt;
&lt;li&gt;string manipulation&lt;/li&gt;
&lt;li&gt;scattered logic&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. It Scales
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Elements&lt;/th&gt;
&lt;th&gt;Total Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;td&gt;0.0222s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;0.9401s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25,000&lt;/td&gt;
&lt;td&gt;5.8194s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;75,000&lt;/td&gt;
&lt;td&gt;77.1450s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Constant-time mutations (~0.001s)&lt;/li&gt;
&lt;li&gt;Designed to handle large UI trees&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📊 About the Performance Chart
&lt;/h3&gt;

&lt;p&gt;The benchmark results are not isolated measurements—they are part of a continuous scaling curve.&lt;/p&gt;

&lt;p&gt;The performance results depend on the rendering paradigm used inside Probo UI.&lt;/p&gt;

&lt;p&gt;Probo UI supports a multi-paradigm rendering model:&lt;/p&gt;

&lt;p&gt;Functional tags (stateless / O(1)-style) → optimized for large-scale rendering&lt;br&gt;
OOP / class-based nodes (mutable SSDOM objects) → richer features, slightly heavier cost&lt;/p&gt;

&lt;p&gt;In optimized functional mode, the same 75,000-node test can render significantly faster (sub-second in controlled cases).&lt;/p&gt;

&lt;p&gt;You can view the full progression from &lt;strong&gt;100 → 75,000 nodes&lt;/strong&gt; here:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://mojahid-0-youness.github.io/probo/performance_chart/" rel="noopener noreferrer"&gt;https://mojahid-0-youness.github.io/probo/performance_chart/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This chart reflects how Probo UI behaves under increasing load across real rendering scenarios.&lt;/p&gt;

&lt;p&gt;The goal is not just raw speed, but predictable scaling behavior across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;small UI components&lt;/li&gt;
&lt;li&gt;medium applications&lt;/li&gt;
&lt;li&gt;large, nested UI trees&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. Why This Matters
&lt;/h2&gt;

&lt;p&gt;Traditional:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python → logic&lt;/li&gt;
&lt;li&gt;HTML → UI&lt;/li&gt;
&lt;li&gt;Templates → glue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Probo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python → logic + UI&lt;/li&gt;
&lt;li&gt;HTML → output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;easier refactoring&lt;/li&gt;
&lt;li&gt;reusable components&lt;/li&gt;
&lt;li&gt;no context switching&lt;/li&gt;
&lt;li&gt;fewer silent template errors&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  9. Framework Agnostic by Design
&lt;/h2&gt;

&lt;p&gt;Probo UI is &lt;strong&gt;not tied to Django or any specific backend framework&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It works as a &lt;strong&gt;UI layer that sits above any Python web framework&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Because Probo UI builds a &lt;strong&gt;Server-Side DOM (SSDOM)&lt;/strong&gt;, it only needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python to construct the UI tree&lt;/li&gt;
&lt;li&gt;A render step to output HTML&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means it can be used with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Django&lt;/li&gt;
&lt;li&gt;Flask&lt;/li&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;Or any custom WSGI/ASGI application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The framework only handles routing and requests.&lt;/p&gt;

&lt;p&gt;Probo handles the UI structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Try It
&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;probo-ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docs:&lt;br&gt;
&lt;a href="https://mojahid-0-youness.github.io/probo/" rel="noopener noreferrer"&gt;https://mojahid-0-youness.github.io/probo/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repo:&lt;br&gt;
&lt;a href="https://github.com/MojahiD-0-YouneSS/probo" rel="noopener noreferrer"&gt;https://github.com/MojahiD-0-YouneSS/probo&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;If your backend is Python…&lt;br&gt;
why are you still writing UI in HTML?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Your Turn
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Would you replace templates with Python?&lt;/li&gt;
&lt;li&gt;Or is this overengineering?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I want honest feedback.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Probo UI 1.4.0 — stable, usable, and just getting started.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>python</category>
      <category>django</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
