<?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: Carlos Salamanca</title>
    <description>The latest articles on DEV Community by Carlos Salamanca (@salamancacm).</description>
    <link>https://dev.to/salamancacm</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%2F3628066%2F9c502f26-39d7-4934-b289-e47176f08759.jpg</url>
      <title>DEV Community: Carlos Salamanca</title>
      <link>https://dev.to/salamancacm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/salamancacm"/>
    <language>en</language>
    <item>
      <title>I Built a Tiny Game for When Your App Takes Too Long to Load</title>
      <dc:creator>Carlos Salamanca</dc:creator>
      <pubDate>Wed, 29 Jul 2026 22:51:53 +0000</pubDate>
      <link>https://dev.to/salamancacm/i-built-a-tiny-game-for-when-your-app-takes-too-long-to-load-1h8b</link>
      <guid>https://dev.to/salamancacm/i-built-a-tiny-game-for-when-your-app-takes-too-long-to-load-1h8b</guid>
      <description>&lt;p&gt;Let's be honest.&lt;/p&gt;

&lt;p&gt;Nobody likes staring at a loading spinner.&lt;/p&gt;

&lt;p&gt;You wait.&lt;/p&gt;

&lt;p&gt;You stare at the screen.&lt;/p&gt;

&lt;p&gt;You wait some more.&lt;/p&gt;

&lt;p&gt;And eventually you start wondering if the application is actually loading… or if it has simply given up on life. 😅&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;BoredLoad&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of making users stare at a spinner while waiting for your application to finish loading, BoredLoad gives them a tiny game to play.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎮 What is BoredLoad?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/salamancacm/boredload" rel="noopener noreferrer"&gt;BoredLoad&lt;/a&gt; is a lightweight, open-source loading component that turns long loading times into a small playable experience.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User starts waiting
       ↓
Loading...
       ↓
Loading takes longer than expected
       ↓
🎮 BoredLoad appears
       ↓
User plays
       ↓
Your content is ready
       ↓
Game disappears
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal isn't to hide slow performance.&lt;/p&gt;

&lt;p&gt;It's simply to make the waiting experience a little less boring.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Try it
&lt;/h2&gt;

&lt;p&gt;You can check out the project here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/salamancacm/boredload" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And install it from npm:&lt;br&gt;
&lt;/p&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;boredload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why did I build it?
&lt;/h2&gt;

&lt;p&gt;I was thinking about something that happens constantly when using web applications:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;loading screens are everywhere.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dashboards load data.&lt;/p&gt;

&lt;p&gt;Apps make API requests.&lt;/p&gt;

&lt;p&gt;Authentication happens.&lt;/p&gt;

&lt;p&gt;Files upload.&lt;/p&gt;

&lt;p&gt;Pages transition.&lt;/p&gt;

&lt;p&gt;Sometimes those operations take a few seconds.&lt;/p&gt;

&lt;p&gt;And during those few seconds, we're usually given the same experience:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       ⏳
    Loading...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I thought:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if the loading screen actually gave you something to do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's where BoredLoad came from.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧑‍💻 Built for developers
&lt;/h2&gt;

&lt;p&gt;BoredLoad is designed to be easy to drop into an existing project.&lt;/p&gt;

&lt;p&gt;It supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Vanilla JavaScript&lt;/li&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Angular&lt;/li&gt;
&lt;li&gt;Vite&lt;/li&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;Touch interaction&lt;/li&gt;
&lt;li&gt;Keyboard interaction&lt;/li&gt;
&lt;li&gt;High scores&lt;/li&gt;
&lt;li&gt;Seeded randomness&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prefers-reduced-motion&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Customizable loading thresholds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the core has &lt;strong&gt;zero runtime dependencies&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The goal was to keep it small enough that adding a tiny game to a loading screen doesn't become a huge performance penalty itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚛️ React example
&lt;/h2&gt;

&lt;p&gt;For example, you can initialize BoredLoad when an operation starts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BoredLoad&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="s2"&gt;boredload&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;boredLoad&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;BoredLoad&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;boredLoad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/data&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;boredLoad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Render your data&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The basic idea is that BoredLoad doesn't need to know what you're loading.&lt;/p&gt;

&lt;p&gt;It simply needs to know:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Are we still waiting?"&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🕹️ Why a game?
&lt;/h2&gt;

&lt;p&gt;There is actually something interesting about turning waiting into interaction.&lt;/p&gt;

&lt;p&gt;A loading spinner is passive.&lt;/p&gt;

&lt;p&gt;The user just watches.&lt;/p&gt;

&lt;p&gt;A game is active.&lt;/p&gt;

&lt;p&gt;Even a tiny interaction can change the perception of waiting.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"Why is this taking so long?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Can I beat my previous score?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's the little experiment behind BoredLoad.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 Designed to be extensible
&lt;/h2&gt;

&lt;p&gt;One of the things I wanted from the beginning was to avoid building a library that only supports one hardcoded experience.&lt;/p&gt;

&lt;p&gt;The project has an extensible game architecture so new mini-games can be added over time.&lt;/p&gt;

&lt;p&gt;The long-term idea is to have several small experiences:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BoredLoad
│
├── 🏃 Runner
├── 🐍 Snake
├── 🧠 Memory
├── 🚀 Space
└── 🧱 Breakout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And potentially allow developers to create their own games.&lt;/p&gt;

&lt;p&gt;Because if you're going to wait…&lt;/p&gt;

&lt;p&gt;you might as well make it interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 Open source
&lt;/h2&gt;

&lt;p&gt;BoredLoad is completely open source and released under the MIT License.&lt;/p&gt;

&lt;p&gt;The repository is available on GitHub:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/salamancacm/boredload" rel="noopener noreferrer"&gt;https://github.com/salamancacm/boredload&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you like the idea, I'd really appreciate a ⭐ on GitHub.&lt;/p&gt;

&lt;p&gt;And if you find a bug, have an idea for a game, or want to contribute, pull requests and issues are welcome.&lt;/p&gt;

&lt;h2&gt;
  
  
  ☕ Support the project
&lt;/h2&gt;

&lt;p&gt;BoredLoad will remain free and open source.&lt;/p&gt;

&lt;p&gt;If you enjoy the project, find it useful, or simply like the idea of making loading screens less boring, you can support its development on Ko-fi.&lt;/p&gt;

&lt;p&gt;Even a small contribution helps me justify spending more time building weird little developer tools like this one. 😄&lt;/p&gt;

&lt;p&gt;☕ &lt;strong&gt;&lt;a href="https://dev.toYOUR_KOFI_LINK"&gt;Support BoredLoad on Ko-fi&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;I'm planning to experiment with more mini-games, better customization, and additional integrations.&lt;/p&gt;

&lt;p&gt;But for now, I just wanted to get the idea out there.&lt;/p&gt;

&lt;p&gt;Maybe loading screens don't have to be boring.&lt;/p&gt;

&lt;p&gt;Maybe we can make waiting a little more fun.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try BoredLoad and let me know what you think.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/salamancacm/boredload" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://www.npmjs.com/package/boredload" rel="noopener noreferrer"&gt;npm&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;⭐ If you like it, consider starring the repository.&lt;/p&gt;

&lt;p&gt;And if you build something with it, I'd love to see it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>I kept seeing weird stuff on my VPS, so I built a tool to stop guessing</title>
      <dc:creator>Carlos Salamanca</dc:creator>
      <pubDate>Sat, 25 Jul 2026 21:07:02 +0000</pubDate>
      <link>https://dev.to/salamancacm/i-kept-seeing-weird-stuff-on-my-vps-so-i-built-a-tool-to-stop-guessing-2808</link>
      <guid>https://dev.to/salamancacm/i-kept-seeing-weird-stuff-on-my-vps-so-i-built-a-tool-to-stop-guessing-2808</guid>
      <description>&lt;p&gt;A few weeks ago I noticed some things I couldn't explain on one of my VPS instances — nothing catastrophic, just enough "that's not right" to make me nervous. I went looking for a lightweight tool to audit and harden a fresh Linux server and mostly found two things: hand-rolled bash scripts of wildly varying quality, or heavyweight compliance scanners built for enterprises running hundreds of servers, not someone with a couple of &lt;code&gt;$5/mo&lt;/code&gt; boxes.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://github.com/salamancacm/vpsguard" rel="noopener noreferrer"&gt;&lt;strong&gt;vpsguard&lt;/strong&gt;&lt;/a&gt; — a single Go binary that audits, hardens, and monitors a Linux VPS, with no dependencies beyond what's already on the box.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2rtee18xdb90ilfdpqhs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2rtee18xdb90ilfdpqhs.gif" alt="vpsguard audit, harden, and monitor catching a simulated SSH key intrusion" width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's a real recording — &lt;code&gt;audit&lt;/code&gt; finding real issues on a stock Ubuntu box, &lt;code&gt;harden&lt;/code&gt; fixing them, and &lt;code&gt;monitor&lt;/code&gt; catching a simulated attacker adding their own SSH key. No staged screenshots.&lt;/p&gt;

&lt;p&gt;Twelve checks in total: SSH config, firewall (ufw &lt;em&gt;and&lt;/em&gt; firewalld — more on that below), fail2ban, suspicious user accounts, SSH key hygiene, cron, pending updates, exposed database ports, Docker socket permissions, kernel/patch status, and (as a beta check) AWS EC2's IMDSv1 exposure — the same SSRF vector behind the Capital One breach.&lt;/p&gt;

&lt;p&gt;Every &lt;code&gt;harden&lt;/code&gt; remediation is idempotent — run it ten times, get the same end state, no duplicated config lines — and every config file it touches gets backed up first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that actually matters: monitor
&lt;/h2&gt;

&lt;p&gt;Audit is nice, but the thing that motivated this whole project was catching &lt;em&gt;change&lt;/em&gt; — someone adding an SSH key you didn't add, a new UID-0 account, a new process running as root. &lt;code&gt;vpsguard monitor&lt;/code&gt; snapshots server state and diffs it against the last run — that's the second half of the GIF above, where it catches the CRIT the instant the attacker's key gets added.&lt;/p&gt;

&lt;p&gt;Wire it to cron (&lt;code&gt;vpsguard install-cron&lt;/code&gt;) and point it at a Slack/Discord webhook or email, and you get pinged instead of finding out three weeks later when you happen to check a log.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running it from CI/CD
&lt;/h2&gt;

&lt;p&gt;If you'd rather bake this into a pipeline than remember to run it yourself, there's a &lt;a href="https://github.com/marketplace/actions/vps-fleet-audit-vpsguard" rel="noopener noreferrer"&gt;GitHub Action&lt;/a&gt; that audits a whole fleet on a schedule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;VPS security audit&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;6&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt; &lt;span class="c1"&gt;# daily at 06:00 UTC&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;audit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;salamancacm/vpsguard-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web-1.example.com,db-1.example.com&lt;/span&gt;
          &lt;span class="na"&gt;ssh-user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
          &lt;span class="na"&gt;ssh-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.VPS_SSH_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;ssh-known-hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.VPS_KNOWN_HOSTS }}&lt;/span&gt;
          &lt;span class="na"&gt;fail-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CRIT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It installs vpsguard on the runner, connects to each host with your own SSH key (never vpsguard's — it doesn't handle credentials), runs the audit, and writes a summary table straight into the workflow's job summary. Set &lt;code&gt;fail-on&lt;/code&gt; to &lt;code&gt;CRIT&lt;/code&gt;, &lt;code&gt;WARN&lt;/code&gt;, or &lt;code&gt;NONE&lt;/code&gt; depending on whether you want a bad finding to actually fail the build or just get reported; it also exposes &lt;code&gt;crit-count&lt;/code&gt;, &lt;code&gt;warn-count&lt;/code&gt;, and &lt;code&gt;unreachable-count&lt;/code&gt; as outputs if you want to branch on them yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few things I'm actually proud of
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It's honest about what it hasn't verified.&lt;/strong&gt; The AWS IMDSv1 check is tagged &lt;code&gt;[BETA]&lt;/code&gt; in its own output, because I built and unit-tested it but never ran it against a real EC2 instance (that would mean spending real money on infra I didn't need). Rather than pretend otherwise, findings from unverified checks are marked, everywhere — table output and &lt;code&gt;--json&lt;/code&gt; both.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real bugs got caught by testing against real systems, not mocks.&lt;/strong&gt; Validating the RHEL/&lt;code&gt;dnf&lt;/code&gt; code path against an actual Rocky Linux container surfaced two genuine bugs: &lt;code&gt;harden&lt;/code&gt; was trying to &lt;code&gt;dnf install ufw&lt;/code&gt; (not in RHEL's repos at all) and the audit checks had no concept of &lt;code&gt;firewalld&lt;/code&gt; — RHEL's actual default firewall — so a properly-secured RHEL box would've been reported as having &lt;em&gt;no firewall at all&lt;/em&gt;. Fixed, and now covered by real Rocky Linux testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;vpsguard fleet&lt;/code&gt;&lt;/strong&gt; audits multiple hosts over SSH at once, using your own SSH config/agent — the same mechanism the GitHub Action above wraps.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installing it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/salamancacm/vpsguard/main/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Checksum-verified against the release, refuses to install on a mismatch — read the script first if piping curl to sh isn't your thing, which is fair.) Also available via &lt;code&gt;go install&lt;/code&gt;, and Homebrew-on-Linux.&lt;/p&gt;

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

&lt;p&gt;Kernel/patch checking on RHEL is solid; broader cloud-provider coverage (Security Group/VPC-level blindness is a real gap right now — vpsguard only sees the OS firewall, not AWS/GCP's network layer) is on the list. If you run a VPS and have five minutes, &lt;code&gt;vpsguard audit&lt;/code&gt; is read-only and won't touch anything — I'd genuinely like to know what it gets wrong on your setup.&lt;/p&gt;

&lt;p&gt;Repo's here: &lt;strong&gt;&lt;a href="https://github.com/salamancacm/vpsguard" rel="noopener noreferrer"&gt;https://github.com/salamancacm/vpsguard&lt;/a&gt;&lt;/strong&gt; — issues, PRs, and "this check is wrong" reports all welcome.&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I built a visual API generator — no code, no prompts, just clean backend projects</title>
      <dc:creator>Carlos Salamanca</dc:creator>
      <pubDate>Tue, 25 Nov 2025 00:05:42 +0000</pubDate>
      <link>https://dev.to/salamancacm/i-built-a-visual-api-generator-no-code-no-prompts-just-clean-backend-projects-5cka</link>
      <guid>https://dev.to/salamancacm/i-built-a-visual-api-generator-no-code-no-prompts-just-clean-backend-projects-5cka</guid>
      <description>&lt;p&gt;✨ &lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For the past few weeks, I’ve been building a tool that I personally needed for a long time:&lt;br&gt;
a way to generate complete backend projects without writing the same boilerplate over and over.&lt;/p&gt;

&lt;p&gt;The result is GenAPI — a visual API generator that lets you design your data models in a UI and then export a fully working backend project.&lt;/p&gt;

&lt;p&gt;🔗 Try it here: &lt;a href="https://thegenapi.io" rel="noopener noreferrer"&gt;https://thegenapi.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(No login required — 100% free at the moment)&lt;/p&gt;




&lt;p&gt;🛠 &lt;strong&gt;Why I built this&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As developers, we constantly repeat the same setup steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;creating models/entities&lt;/li&gt;
&lt;li&gt;defining controllers/services&lt;/li&gt;
&lt;li&gt;configuring routes&lt;/li&gt;
&lt;li&gt;setting up project structure&lt;/li&gt;
&lt;li&gt;writing CRUD logic&lt;/li&gt;
&lt;li&gt;preparing basic validations&lt;/li&gt;
&lt;li&gt;wiring everything into a backend framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After doing this hundreds of times across Node, Java, Python and PHP projects, I wanted a faster way.&lt;/p&gt;

&lt;p&gt;Not AI-generated code.&lt;br&gt;
Not templates.&lt;br&gt;
A real visual builder that outputs a clean, ready-to-run backend.&lt;/p&gt;




&lt;p&gt;🧩 &lt;strong&gt;How GenAPI works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The workflow is very simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the visual builder&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You start with an empty canvas where you can create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entities&lt;/li&gt;
&lt;li&gt;Fields&lt;/li&gt;
&lt;li&gt;Types&lt;/li&gt;
&lt;li&gt;Relationships&lt;/li&gt;
&lt;li&gt;Optional constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Choose your backend framework&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once your models are ready, you pick the stack you want to export to.&lt;/p&gt;

&lt;p&gt;Right now GenAPI supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java (Spring Boot)&lt;/li&gt;
&lt;li&gt;Java (Quarkus)&lt;/li&gt;
&lt;li&gt;Node.js (Express)&lt;/li&gt;
&lt;li&gt;Python (FastAPI)&lt;/li&gt;
&lt;li&gt;PHP (Laravel)&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Download the generated ZIP&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GenAPI creates a complete backend project with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Models / Entities&lt;/li&gt;
&lt;li&gt;Controllers&lt;/li&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;li&gt;Routes&lt;/li&gt;
&lt;li&gt;Basic CRUD logic&lt;/li&gt;
&lt;li&gt;Validations&lt;/li&gt;
&lt;li&gt;Clean folder structure&lt;/li&gt;
&lt;li&gt;Dependencies installed&lt;/li&gt;
&lt;li&gt;A README with instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 You run it locally and it just works.&lt;/p&gt;

&lt;p&gt;No prompts.&lt;br&gt;
No AI guesswork.&lt;br&gt;
Just deterministic code based on your entities.&lt;/p&gt;




&lt;p&gt;🎁 &lt;strong&gt;New feature: Starter Templates&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To help new users get started quickly, I’m adding starter templates inside the builder:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blog API&lt;/li&gt;
&lt;li&gt;E-commerce&lt;/li&gt;
&lt;li&gt;Booking System&lt;/li&gt;
&lt;li&gt;CRM Lite&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These load pre-made entities so you can test the tool instantly.&lt;/p&gt;




&lt;p&gt;🚀 &lt;strong&gt;Who is GenAPI for?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This tool is ideal if you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;build prototypes frequently&lt;/li&gt;
&lt;li&gt;generate small/medium backends&lt;/li&gt;
&lt;li&gt;teach backend development&lt;/li&gt;
&lt;li&gt;want to speed up CRUD-heavy work&lt;/li&gt;
&lt;li&gt;start many client projects&lt;/li&gt;
&lt;li&gt;hate repeating boilerplate code&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🧪 &lt;strong&gt;What I’m currently working on&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More export options&lt;/li&gt;
&lt;li&gt;Better UI for relationships&lt;/li&gt;
&lt;li&gt;SAP CAP export (CDS-based, OData out of the box)&lt;/li&gt;
&lt;li&gt;Auto-documented APIs&lt;/li&gt;
&lt;li&gt;Advanced constraints&lt;/li&gt;
&lt;li&gt;Microservice export mode&lt;/li&gt;
&lt;li&gt;A VSCode extension to sync entities&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🙏 &lt;strong&gt;I’d love your feedback&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since GenAPI is still early, feedback from the dev community is extremely helpful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the builder intuitive?&lt;/li&gt;
&lt;li&gt;Does the generated code look clean?&lt;/li&gt;
&lt;li&gt;What frameworks should I add next?&lt;/li&gt;
&lt;li&gt;Would this be useful in your workflow?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comments are 100% welcome.&lt;/p&gt;

&lt;p&gt;🔗 Try it here: &lt;a href="https://thegenapi.io" rel="noopener noreferrer"&gt;https://thegenapi.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading! 🚀&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>backend</category>
      <category>productivity</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
