<?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: Michal Král</title>
    <description>The latest articles on DEV Community by Michal Král (@kralik12).</description>
    <link>https://dev.to/kralik12</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%2F21797%2F85ec1aeb-60ac-446f-abc8-9ad2177d1422.jpg</url>
      <title>DEV Community: Michal Král</title>
      <link>https://dev.to/kralik12</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kralik12"/>
    <language>en</language>
    <item>
      <title>A little tool for watching algorithms run</title>
      <dc:creator>Michal Král</dc:creator>
      <pubDate>Wed, 17 Jun 2026 14:19:24 +0000</pubDate>
      <link>https://dev.to/kralik12/a-little-tool-for-watching-algorithms-run-4abk</link>
      <guid>https://dev.to/kralik12/a-little-tool-for-watching-algorithms-run-4abk</guid>
      <description>&lt;p&gt;I've always found algorithms easier to understand once I can &lt;em&gt;see&lt;/em&gt; them move. Pseudocode and textbook diagrams are fine, but for a lot of things — how a sort actually rearranges elements, why Dijkstra picks the path it does — a static picture only gets me so far. I usually end up tracing through it by hand on paper.&lt;/p&gt;

&lt;p&gt;So I made a small thing to do that tracing for me: &lt;strong&gt;&lt;a href="https://bigoh.dev" rel="noopener noreferrer"&gt;bigoh.dev&lt;/a&gt;&lt;/strong&gt;. It's free, open, and meant for learning. Sharing it here in case it's useful to anyone else who thinks the same way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;You pick an algorithm or data structure, edit the input, and press play. It runs step by step on a canvas. Below the animation there's a short description of what's happening at the current step, and the pseudocode with the active line highlighted. You can step forward and back, or scrub a timeline to jump around. That's basically it.&lt;/p&gt;

&lt;p&gt;A few of the visualizations are interactive in a way that helps: on graphs you click to add nodes and edges, on grids you click to toggle walls, and on the geometry plane you click to drop points. Then you watch the algorithm run on the thing you just drew.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's covered
&lt;/h2&gt;

&lt;p&gt;There are around 67 visualizations right now, grouped roughly like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sorting&lt;/strong&gt; — bubble, quick, merge, heap, counting, radix, and the usual rest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Searching&lt;/strong&gt; — binary, jump, interpolation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data structures&lt;/strong&gt; — stack, queue, deque, linked list, hash table, BST, heap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trees &amp;amp; graphs&lt;/strong&gt; — traversals, BFS, DFS, Dijkstra, Bellman-Ford, MST (Prim, Kruskal, Borůvka), topological sort, connected components, cycle detection, bipartite check, Floyd-Warshall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pathfinding &amp;amp; mazes&lt;/strong&gt; — BFS, A*, greedy best-first, Dijkstra on weighted terrain, bidirectional search, plus maze generation (recursive backtracker, Prim, Wilson).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic programming&lt;/strong&gt; — edit distance, LCS, coin change, subset sum, knapsack (0/1 and unbounded), partition, Kadane, LIS, Fibonacci.&lt;/li&gt;
&lt;li&gt;And I try to expand the list&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  One example
&lt;/h2&gt;

&lt;p&gt;The pathfinding ones are where seeing it move helped me most. Run plain BFS on a grid and it spreads out evenly in all directions, like a flood — it has no idea where the goal is. Switch to A* on the same grid and the explored area visibly leans toward the target, because it's using a heuristic to guess which direction is worth checking first. Watching the two side by side made the difference click for me in a way that "A* is informed search" never did.&lt;/p&gt;

&lt;p&gt;Dijkstra on weighted terrain is similar: you can watch it deliberately detour around the expensive squares instead of just taking the straight line, and suddenly the cost function isn't abstract anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  On the tech
&lt;/h2&gt;

&lt;p&gt;For the developers here: it's built with Vue 3, with the visualizations drawn on canvas using &lt;a href="https://konvajs.org/" rel="noopener noreferrer"&gt;Konva&lt;/a&gt;. Each algorithm produces a list of steps up front, and the player just renders whichever step you're on — which is what makes stepping back and scrubbing work. The pages are statically prerendered so they load quickly and are reasonably friendly to search engines.&lt;/p&gt;

&lt;h2&gt;
  
  
  That's it
&lt;/h2&gt;

&lt;p&gt;It's a hobby project and still growing, so there are rough edges and gaps. If you try it and something is confusing, broken, or just missing an algorithm you wanted to see, I'd genuinely like to hear about it — suggestions for what to add next are very welcome.&lt;/p&gt;

&lt;p&gt;Here it is: &lt;strong&gt;&lt;a href="https://bigoh.dev" rel="noopener noreferrer"&gt;bigoh.dev&lt;/a&gt;&lt;/strong&gt;. Thanks for reading.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>learning</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>I love MJML — I just didn't want a whole templating engine for two tiny things</title>
      <dc:creator>Michal Král</dc:creator>
      <pubDate>Wed, 27 May 2026 11:19:34 +0000</pubDate>
      <link>https://dev.to/kralik12/i-love-mjml-i-just-didnt-want-a-whole-templating-engine-for-two-tiny-things-5a10</link>
      <guid>https://dev.to/kralik12/i-love-mjml-i-just-didnt-want-a-whole-templating-engine-for-two-tiny-things-5a10</guid>
      <description>&lt;p&gt;I love MJML.&lt;/p&gt;

&lt;p&gt;Responsive HTML email is one of the genuinely miserable corners of frontend — nested tables, &lt;code&gt;&amp;lt;!--[if mso]&amp;gt;&lt;/code&gt; incantations, clients from 2007 that still get a vote. MJML takes all of that and lets me write semantic-ish components (&lt;code&gt;&amp;lt;mj-section&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;mj-column&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;mj-button&amp;gt;&lt;/code&gt;) that compile down to email HTML that actually renders everywhere. It's one of those tools that makes a horrible problem boring, which is the highest compliment I can give a library.&lt;/p&gt;

&lt;p&gt;So I was happy. Except for one thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one thing I was missing
&lt;/h2&gt;

&lt;p&gt;My templates needed two unglamorous things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Variables&lt;/strong&gt; — drop a name, a URL, an order number into the email.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Translations&lt;/strong&gt; — the same template in &lt;code&gt;en&lt;/code&gt;, &lt;code&gt;cs&lt;/code&gt;, whatever.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;MJML doesn't do either, and fair enough — it's a markup compiler, not a template engine. So like a lot of people, I reached for the template engine I already had and ran my &lt;code&gt;.mjml&lt;/code&gt; files &lt;strong&gt;through Twig first&lt;/strong&gt;, just to get this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;mj-text&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="s1"&gt;'welcome.hello'&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nf"&gt;trans&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'%name%'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/mj-text&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it worked. But look at what that actually is: I'm spinning up an entire templating engine — with loops, conditionals, filters, its own parsing pass — to do &lt;em&gt;string interpolation and a dictionary lookup&lt;/em&gt;. Two compile steps (Twig → MJML) for what should be one. A second syntax in my files. And every time I touched a template I had to keep two mental models in sync.&lt;/p&gt;

&lt;p&gt;I didn't want a template engine in my email pipeline. I wanted those &lt;strong&gt;two tiny things&lt;/strong&gt; — and nothing else.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually wanted
&lt;/h2&gt;

&lt;p&gt;Co-located translations, vue-i18n style — the strings living right next to the markup that uses them — plus dead-simple variable access. Something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;mjml&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;i18n&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"json"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {
      "en": { "hello": "Hello {name}!", "cta": "Shop now" },
      "cs": { "hello": "Ahoj {name}!", "cta": "Nakupovat" }
    }
  &lt;span class="nt"&gt;&amp;lt;/i18n&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;mj-body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;mj-section&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;mj-column&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;mj-text&amp;gt;&lt;/span&gt;{{ i18n('hello', { name: get('firstName') }) }}&lt;span class="nt"&gt;&amp;lt;/mj-text&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;mj-button&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{{ get('url') }}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ i18n('cta') }}&lt;span class="nt"&gt;&amp;lt;/mj-button&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/mj-column&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/mj-section&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/mj-body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/mjml&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No second template language. No second compile. Just &lt;code&gt;i18n()&lt;/code&gt; and &lt;code&gt;get()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So I built it: &lt;strong&gt;&lt;code&gt;@checkthiscloud/mjml-i18n&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using it
&lt;/h2&gt;

&lt;p&gt;It's a single MJML preprocessor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mjml&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mjml&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createI18nPreprocessor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@checkthiscloud/mjml-i18n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;preprocessor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createI18nPreprocessor&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;vars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ada&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;mjml&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;preprocessors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;preprocessor&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;That's the whole integration. One preprocessor in, fully resolved email HTML out.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works (and what it deliberately &lt;em&gt;doesn't&lt;/em&gt; do)
&lt;/h2&gt;

&lt;p&gt;The trick is that it runs as an &lt;strong&gt;MJML preprocessor&lt;/strong&gt; — it resolves the &lt;code&gt;{{ … }}&lt;/code&gt; markers on the &lt;strong&gt;raw XML, before MJML parses it&lt;/strong&gt;. Two nice consequences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Markers work &lt;strong&gt;anywhere&lt;/strong&gt;, including inside attributes (&lt;code&gt;href="{{ get('url') }}"&lt;/code&gt;), not just text nodes.&lt;/li&gt;
&lt;li&gt;It composes with MJML instead of fighting it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside each &lt;code&gt;{{ … }}&lt;/code&gt; is a single &lt;strong&gt;function-call expression&lt;/strong&gt;, evaluated by a tiny allowlist (built on &lt;a href="https://github.com/EricSmekens/jsep" rel="noopener noreferrer"&gt;jsep&lt;/a&gt;). Only literals, object arguments, and the registered functions (&lt;code&gt;i18n&lt;/code&gt;, &lt;code&gt;get&lt;/code&gt;) are allowed. You can nest them — &lt;code&gt;i18n('hello', { name: get('firstName') })&lt;/code&gt; — and that's it.&lt;/p&gt;

&lt;p&gt;What it is &lt;strong&gt;not&lt;/strong&gt; is a template engine. No loops, no conditionals, no arbitrary expressions, no &lt;code&gt;eval&lt;/code&gt;. If a marker isn't a recognized call, it's left untouched rather than executed. That constraint is the whole point: I wanted the two things I was missing, not a Turing-complete language living in my emails.&lt;/p&gt;

&lt;p&gt;Translations fall back gracefully (missing key → the key, missing variable → an obvious placeholder), so a typo degrades instead of exploding mid-render.&lt;/p&gt;

&lt;h2&gt;
  
  
  Status
&lt;/h2&gt;

&lt;p&gt;It's young — &lt;code&gt;0.x&lt;/code&gt;, MIT, built for MJML v5 — but small and focused, and it does exactly what it says. Params are currently plain &lt;code&gt;{name}&lt;/code&gt; substitution (no ICU plurals yet, though the seam is there if that day comes). If you live in MJML and you've been bolting a template engine onto it just for translations, give it a spin and tell me where it breaks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/@checkthiscloud/mjml-i18n" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@checkthiscloud/mjml-i18n&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/CheckThisCloud/mjml-i18n" rel="noopener noreferrer"&gt;https://github.com/CheckThisCloud/mjml-i18n&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @checkthiscloud/mjml-i18n mjml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes the feature you want isn't "more" — it's &lt;em&gt;exactly two small things and nothing else&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>mjml</category>
      <category>i18n</category>
      <category>opensource</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Generate Human-Friendly Random Codes in PHP with Crockford’s Base32</title>
      <dc:creator>Michal Král</dc:creator>
      <pubDate>Tue, 30 Sep 2025 18:24:28 +0000</pubDate>
      <link>https://dev.to/kralik12/generate-human-friendly-random-codes-in-php-with-crockfords-base32-fob</link>
      <guid>https://dev.to/kralik12/generate-human-friendly-random-codes-in-php-with-crockfords-base32-fob</guid>
      <description>&lt;p&gt;Generating random codes sounds easy — until real people have to read, type, or say them out loud. Suddenly &lt;code&gt;O&lt;/code&gt; looks like &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;l&lt;/code&gt; looks like &lt;code&gt;1&lt;/code&gt;, and half your support tickets are about users mistyping their coupon or entry code.  &lt;/p&gt;

&lt;p&gt;To solve this, I built a small PHP library that generates &lt;strong&gt;human-friendly random strings&lt;/strong&gt; using &lt;strong&gt;Crockford’s Base32 alphabet&lt;/strong&gt;. It’s perfect for things like &lt;strong&gt;coupon codes, ticket entry codes, invite tokens, or any other short identifiers&lt;/strong&gt; where clarity matters just as much as randomness.  &lt;/p&gt;

&lt;p&gt;👉 GitHub repo: &lt;a href="https://github.com/CheckThisCloud/CrockfordRandom" rel="noopener noreferrer"&gt;CheckThisCloud/CrockfordRandom&lt;/a&gt;  &lt;/p&gt;




&lt;h2&gt;
  
  
  Why Crockford’s Base32?
&lt;/h2&gt;

&lt;p&gt;When generating codes for humans to type in or read back, you don’t want people misreading &lt;code&gt;O&lt;/code&gt; as &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;l&lt;/code&gt; as &lt;code&gt;1&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Crockford’s alphabet solves this by removing ambiguous characters while keeping the string compact and case-insensitive.  &lt;/p&gt;




&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Generate random strings of any length.
&lt;/li&gt;
&lt;li&gt;Ideal for human-facing codes: &lt;strong&gt;tickets, coupons, invites, promo codes&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Output uses only unambiguous characters.
&lt;/li&gt;
&lt;li&gt;Built on PHP’s modern &lt;code&gt;Random\Randomizer&lt;/code&gt; class.
&lt;/li&gt;
&lt;li&gt;Tiny footprint — easy to drop into any project.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Example usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;CheckThisCloud\CrockfordRandom\CrockfordRandom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CrockfordRandom&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$random&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// Example output: 9XF7T2K4HZ&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bonus: SillyNames 🎉
&lt;/h3&gt;

&lt;p&gt;I’ve also built another micro-library: [CheckThisCloud/SillyNames]((&lt;a href="https://github.com/CheckThisCloud/SillyNames" rel="noopener noreferrer"&gt;https://github.com/CheckThisCloud/SillyNames&lt;/a&gt;)&lt;br&gt;
.&lt;br&gt;
It generates random two-word names in the style of Docker container names (e.g. brave_panda, sleepy_hedgehog).&lt;br&gt;
Useful for test data, logs, or giving projects some personality.&lt;/p&gt;

&lt;p&gt;Feedback is very welcome 🙏&lt;/p&gt;

</description>
      <category>php</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
