<?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: Keith Solomon </title>
    <description>The latest articles on DEV Community by Keith Solomon  (@ksolomon).</description>
    <link>https://dev.to/ksolomon</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%2F1127873%2F76c538fd-0973-4651-b8e0-8f2bf6e62f85.png</url>
      <title>DEV Community: Keith Solomon </title>
      <link>https://dev.to/ksolomon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ksolomon"/>
    <language>en</language>
    <item>
      <title>Weekend Rec Builds: 3D Print Estimator</title>
      <dc:creator>Keith Solomon </dc:creator>
      <pubDate>Mon, 08 Dec 2025 04:27:52 +0000</pubDate>
      <link>https://dev.to/ksolomon/weekend-rec-builds-3d-print-estimator-3pk9</link>
      <guid>https://dev.to/ksolomon/weekend-rec-builds-3d-print-estimator-3pk9</guid>
      <description>&lt;p&gt;This project started (as so many do) with a message from my brother with 2 links.  He was looking at printing some stuff for his kid, and asked the inevitable question:&lt;/p&gt;

&lt;p&gt;“How much filament will this use, and how long will it take?”&lt;/p&gt;

&lt;p&gt;And there were only 100 individual STL files to check.&lt;/p&gt;

&lt;p&gt;Sure, my slicer could give estimates, but opening each file, slicing it, and checking the stats was tedious and time-consuming.&lt;/p&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.amazonaws.com%2Fuploads%2Farticles%2Ffawvr7p4p2usk5gvznvw.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2Ffawvr7p4p2usk5gvznvw.jpg" alt="ain't nobody got time for that!" width="700" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’ve spent any amount of time around 3D printers, you already know the eternal struggle:&lt;/p&gt;

&lt;p&gt;“How long is this going to take?”&lt;br&gt;
“How much filament will this use?”&lt;br&gt;
“Do I have enough left to print this without discovering sadness at 3 a.m.?”&lt;/p&gt;

&lt;p&gt;So for this week’s Weekend Rec Build, I put together something I’ve wanted for a long time: a stand-alone, slicer-agnostic print estimator that can scan STL files directly and give you reasonably accurate numbers for filament length, filament mass, and print time. From the command line or a lightweight web interface.&lt;/p&gt;

&lt;p&gt;The project lives here: &lt;a href="https://github.com/Solo-Web-Works/3D-Print-Estimator" rel="noopener noreferrer"&gt;https://github.com/Solo-Web-Works/3D-Print-Estimator&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Build This?
&lt;/h2&gt;

&lt;p&gt;A surprising amount of 3D printing workflow friction happens before slicing.&lt;/p&gt;

&lt;p&gt;If you maintain a library of dozens (or hundreds) of STLs, the usual preview-slice-estimate loop becomes tedious fast. I wanted something that works like a “pre-slicer inspector” — a little utility I can drop into any folder (or drop it into a folder in my path) and instantly get meaningful estimates.&lt;/p&gt;

&lt;p&gt;Being able to run &lt;code&gt;python estimator.py&lt;/code&gt; and get a spreadsheet of everything in the directory is incredibly convenient.&lt;/p&gt;
&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;At its core, the estimator analyzes STL geometry directly, binary or ASCII, and computes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Volume&lt;/li&gt;
&lt;li&gt;Surface area&lt;/li&gt;
&lt;li&gt;Bounding box dimensions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of that happens in &lt;code&gt;read_stl()&lt;/code&gt; and &lt;code&gt;accumulate_triangle_stats()&lt;/code&gt; in estimator.py, where the script walks every triangle in the mesh, updating bounds, area, and signed tetrahedral volume to get an accurate solid volume.&lt;/p&gt;

&lt;p&gt;Once the raw geometry is known, the next step is turning that into actual printable material and time estimates. That logic lives in the &lt;code&gt;estimate()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Here’s what the estimator computes:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Shell Volume
&lt;/h3&gt;

&lt;p&gt;The surface area is multiplied by the shell thickness:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;shell_thickness = settings.perimeter_count * settings.nozzle_diameter_mm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shell_volume = stats.surface_area_mm2 * shell_thickness&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Is it perfect? No.&lt;br&gt;
Is it “good enough for predicting if I have enough filament left on the spool?” Absolutely.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Infill Volume
&lt;/h3&gt;

&lt;p&gt;Whatever remains after subtracting shell volume becomes the interior. That gets scaled by the infill percentage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;internal_volume = max(stats.volume_mm3 - shell_volume, 0.0)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;infill_volume = internal_volume * settings.infill_density&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  3. Filament Usage
&lt;/h3&gt;

&lt;p&gt;From the estimated extrusion volume, the script computes filament length and mass:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;filament_cross_section = π * (diameter / 2)^2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;filament_length = total_extrusion_volume / filament_cross_section&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;filament_mass = (total_extrusion_volume / 1000) * density&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where your actual filament density pays off.  PLA, PETG, ABS, and infused filaments all vary, so the config file lets you dial that in.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Time Estimate
&lt;/h3&gt;

&lt;p&gt;Finally, the estimator uses three print speeds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perimeter speed&lt;/li&gt;
&lt;li&gt;Infill speed&lt;/li&gt;
&lt;li&gt;Travel speed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Actual slicers know more about retractions, acceleration, jerk, and optimization paths.  This tool intentionally doesn’t. The goal is useful approximations, not G-code-level precision.&lt;/p&gt;

&lt;p&gt;Still, the heuristic works surprisingly well.&lt;/p&gt;
&lt;h2&gt;
  
  
  Two Ways to Use It
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Command Line Mode
&lt;/h3&gt;

&lt;p&gt;As long as Python is on your system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python estimator.py --config printer-config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It scans all .stl files in the folder and outputs CSV by default.&lt;/p&gt;

&lt;p&gt;You can choose JSON or XLSX instead. The XLSX mode even builds formulas for totals and human-readable hour/minute formatting, all handled in &lt;code&gt;build_workbook()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Output sample (formatting added after generation):&lt;/p&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.amazonaws.com%2Fuploads%2Farticles%2Fv5cqarmuo62ztlq3jl6i.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fv5cqarmuo62ztlq3jl6i.png" alt="Excel screenshot" width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Totals row automatically generated&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Web Interface Mode
&lt;/h3&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python estimator.py --serve --port 5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;a href="http://localhost:5000" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt;, upload an STL (or ZIP of STLs), and get a clean table of results. You can even offer downloads as CSV, JSON, or XLSX.  Not by writing files, but by embedding them as data URIs for one-click downloading.&lt;/p&gt;

&lt;p&gt;The web mode is entirely self-contained - no templates, no external static files - and uses a simple Flask-rendered HTML string defined as &lt;code&gt;WEB_TEMPLATE&lt;/code&gt; in the script.&lt;/p&gt;

&lt;p&gt;Web UI sample:&lt;/p&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.amazonaws.com%2Fuploads%2Farticles%2F99ul6zkkd6pa9ocu5g3k.png" 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.amazonaws.com%2Fuploads%2Farticles%2F99ul6zkkd6pa9ocu5g3k.png" alt="Web UI sample" width="800" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration: Your Printer, Your Rules
&lt;/h2&gt;

&lt;p&gt;Everything about your printer setup lives in printer-config.json, documented in the project’s README.md.  These setting will typically mirror your slicer profile, but you can tweak them independently if you want to experiment with different speeds, layer heights, or infill percentages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "layer_height_mm": 0.2,
  "nozzle_diameter_mm": 0.4,
  "perimeter_count": 2,
  "top_layers": 4,
  "bottom_layers": 4,
  "infill_density": 0.25,
  "perimeter_speed_mm_s": 40.0,
  "infill_speed_mm_s": 60.0,
  "travel_speed_mm_s": 120.0,
  "filament_diameter_mm": 1.75,
  "filament_density_g_cm3": 1.24,
  "travel_factor": 0.1
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change it to match your printer, material, or printing preferences, and the estimator updates automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Isn’t
&lt;/h2&gt;

&lt;p&gt;This tool is not trying to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace your slicer&lt;/li&gt;
&lt;li&gt;Predict print time down to the minute&lt;/li&gt;
&lt;li&gt;Handle variable layer heights&lt;/li&gt;
&lt;li&gt;Model retraction, coasting, acceleration, or machine-specific quirks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But it is aiming to answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Do I have enough filament?”&lt;/li&gt;
&lt;li&gt;“Ballpark, how long will these prints take?”&lt;/li&gt;
&lt;li&gt;“Which of these STLs is going to be a weekend print and which is a coffee break?”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’s exactly the problem it solves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where It Goes Next
&lt;/h2&gt;

&lt;p&gt;Future improvements I’m toying with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Per-model config overrides&lt;/li&gt;
&lt;li&gt;Optional real-world calibration (feed it a known model + real print time, adjust heuristics)&lt;/li&gt;
&lt;li&gt;A nicer web UI (I'm not a designer!)&lt;/li&gt;
&lt;li&gt;A batch “compare the cost of these print settings” mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one of those projects that’s small enough to stay enjoyable, but deep enough to keep offering fun ideas.&lt;/p&gt;

</description>
      <category>recreationalcoding</category>
      <category>3dprinting</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>Weekend Rec Build: cifs-watch</title>
      <dc:creator>Keith Solomon </dc:creator>
      <pubDate>Mon, 20 Oct 2025 19:31:07 +0000</pubDate>
      <link>https://dev.to/ksolomon/weekend-rec-build-cifs-watch-4pb7</link>
      <guid>https://dev.to/ksolomon/weekend-rec-build-cifs-watch-4pb7</guid>
      <description>&lt;p&gt;It all started with an email from my Proxmox box, saying that the boot partition was out of space…&lt;/p&gt;

&lt;p&gt;Every homelab has that one little annoyance that slowly drives you up the wall. For me, it was CIFS shares occasionally dropping off the radar. Sometimes it’s the network hiccuping, sometimes it’s the file server rebooting, and sometimes it’s just gremlins. Either way, when a mount goes stale, it breaks workflows and backups alike. So this weekend’s build tackled exactly that.&lt;br&gt;
The Problem&lt;/p&gt;

&lt;p&gt;I’ve got a handful of CIFS mounts defined in &lt;code&gt;/etc/fstab&lt;/code&gt; across several machines, all pointing back to my central file server. When that server or a network hop goes down, the mounts don’t always recover cleanly. Manually remounting them works fine, but doing that across half a dozen machines? Not sustainable.&lt;br&gt;
The Solution&lt;/p&gt;

&lt;p&gt;Enter cifs-watch — a lightweight Bash script that monitors all CIFS mounts listed in &lt;code&gt;/etc/fstab&lt;/code&gt;, checks if they’re reachable, and automatically remounts them when they’re not. It’s polite about it too: it verifies that the file server is online first, logs its actions, and only touches mounts that actually need fixing.&lt;/p&gt;

&lt;p&gt;Think of it as a health check for your network shares. The script runs silently in the background, and you can set it up as a systemd timer or cron job depending on your setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;It’s a very simple script at it’s heart. There are four main processes it wraps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scans &lt;code&gt;/etc/fstab&lt;/code&gt; for lines using the cifs filesystem type.&lt;/li&gt;
&lt;li&gt;Verifies whether each mount target is currently available.&lt;/li&gt;
&lt;li&gt;Pings the host to confirm it’s up before attempting a remount.&lt;/li&gt;
&lt;li&gt;Logs every action — successful checks, reconnections, and errors — to &lt;code&gt;/var/log/cifs-watch.log&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Setup is simple: drop the script into &lt;code&gt;/usr/local/bin/&lt;/code&gt;, make it executable, and add it to cron or a timer unit. That’s it. Your mounts stay connected, your logs stay clean, and your sanity stays intact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why It Matters
&lt;/h2&gt;

&lt;p&gt;In the spirit of Weekend Rec Builds, cifs-watch isn’t a massive overhaul or flashy new service — it’s one of those little quality-of-life automations that keeps the lab running smoothly. Small scripts like this free up brainspace for the next big idea (and save a few “why isn’t this mounted?” headaches along the way).&lt;/p&gt;

</description>
      <category>recreationalcoding</category>
      <category>devjournal</category>
      <category>homelab</category>
      <category>scripting</category>
    </item>
    <item>
      <title>Weekend Rec Build: Hall of the Dwarven King – Web Edition</title>
      <dc:creator>Keith Solomon </dc:creator>
      <pubDate>Mon, 08 Sep 2025 11:43:21 +0000</pubDate>
      <link>https://dev.to/ksolomon/weekend-rec-build-hall-of-the-dwarven-king-web-edition-340p</link>
      <guid>https://dev.to/ksolomon/weekend-rec-build-hall-of-the-dwarven-king-web-edition-340p</guid>
      <description>&lt;p&gt;Sometimes a project doesn’t need to be a sprawling framework or a months-long refactor. Sometimes it’s just about taking something you love and making it more fun to play with.&lt;/p&gt;

&lt;p&gt;This weekend, I built a &lt;a href="https://github.com/Solo-Web-Works/Hall-of-the-Dwarven-King" rel="noopener noreferrer"&gt;browser-based version&lt;/a&gt; of the solo roll-and-build game &lt;em&gt;&lt;a href="https://metalsnail.itch.io/hall-of-the-dwarven-king" rel="noopener noreferrer"&gt;Hall of the Dwarven King&lt;/a&gt;&lt;/em&gt; by Robin Gibson. The idea was simple: keep the heart of the original paper sheet, but drop the pencil-and-bookkeeping overhead. What came out is a quick, single-player web edition that’s fast, friendly, and saves your progress automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Play through 20 turns of dice-driven actions (Fight, Drink, Cook, Dig, Build, Mine).&lt;/li&gt;
&lt;li&gt;Drop buildings onto a 5×5 grid with depth, adjacency, and uniqueness rules.&lt;/li&gt;
&lt;li&gt;Earn and spend gold — funding Vaults, a Throne Room, or even a one-off die face change.&lt;/li&gt;
&lt;li&gt;Auto-resolve phases and scoring so you can just focus on choices.&lt;/li&gt;
&lt;li&gt;Autosave and resume later; keep a small local leaderboard of your best runs.&lt;/li&gt;
&lt;li&gt;Share a one-line score summary straight to your clipboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To try it, all you need to do is download the repo from the above link and open &lt;code&gt;index.html&lt;/code&gt; in a modern browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Rules in a Nutshell
&lt;/h2&gt;

&lt;p&gt;The game plays out with 7 dice that cover everything from Fighting (⚔️) to Mining (💰). Each turn flows like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rolling Phase — Roll, reroll (discarding dice if needed), or spend 5 gold to set a die.&lt;/li&gt;
&lt;li&gt;Action Phase — Resolve in order: Fight → Drink → Cook → Dig → Build → Mine.&lt;/li&gt;
&lt;li&gt;Cleanup — Advance the clock, crown your Throne Room if you have one, and move on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A few wrinkles keep it spicy: Cooking acts as a gate (skip it and you lose the rest of the turn unless you’ve got a Mushroom Farm on your current level), depth increases every 3 digs, and mining scales in risk/reward as you descend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Web Version
&lt;/h2&gt;

&lt;p&gt;I kept the stack deliberately light:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plain HTML/CSS/JS&lt;/strong&gt;. No frameworks, no bundlers.&lt;br&gt;
&lt;strong&gt;State in a JS object&lt;/strong&gt;. Turn, depth, gold, dice rolls, map, everything.&lt;br&gt;
&lt;strong&gt;Persistence via localStorage&lt;/strong&gt;. Games autosave and can be resumed after a refresh.&lt;br&gt;
&lt;strong&gt;Imperative rendering&lt;/strong&gt;. Simple DOM updates, no virtual DOM needed.&lt;/p&gt;

&lt;p&gt;The UI mirrors the original sheet but leans on responsive CSS and inline icons to feel at home on the web. Leaderboard scores stay local (top 5), and guardrails in the code ensure you only see the actions valid for the current phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Few Design Calls
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Explicit reroll selection. Click dice to mark them for reroll (more intuitive than “hold to exclude”).&lt;/li&gt;
&lt;li&gt;Simplified digging pace. One depth every 3 steps — fast enough for web play, still tense.&lt;/li&gt;
&lt;li&gt;Responsive layout. Grid + CSS icons instead of lifting image slices from the paper version.&lt;/li&gt;
&lt;li&gt;Light guardrails. The UI simply doesn’t let you take invalid moves.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where It Could Go Next
&lt;/h2&gt;

&lt;p&gt;The current version is a fully-playable game, but there’s room for polish:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make “Set Face” targetable instead of auto-assigning.&lt;/li&gt;
&lt;li&gt;Rename some legacy variables (&lt;code&gt;held&lt;/code&gt; → &lt;code&gt;selected&lt;/code&gt;) for clarity.&lt;/li&gt;
&lt;li&gt;Add micro-animations to dice rolls and map placements.&lt;/li&gt;
&lt;li&gt;Improve touch/mobile usability with bigger targets and long-press gestures.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Build?
&lt;/h2&gt;

&lt;p&gt;Because sometimes you just want to play a game you love in a slightly different way, and because coding it is half the fun. This one took a weekend: a handful of files, a few hundred lines of vanilla JS, and I’ve now got a snappy little adaptation that anyone can open in a browser and enjoy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attribution
&lt;/h2&gt;

&lt;p&gt;This web version is a fan-made, non-commercial adaptation of &lt;em&gt;Hall of the Dwarven King&lt;/em&gt; (v1.2, 2017) by Robin Gibson — &lt;a href="http://metalsnail.net" rel="noopener noreferrer"&gt;metalsnail.net&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devjournal</category>
      <category>weekend</category>
      <category>recreationaldev</category>
    </item>
    <item>
      <title>Unexpected Transformations: A Year of Growth Through Adversity</title>
      <dc:creator>Keith Solomon </dc:creator>
      <pubDate>Fri, 10 Jan 2025 13:00:08 +0000</pubDate>
      <link>https://dev.to/ksolomon/unexpected-transformations-a-year-of-growth-through-adversity-500d</link>
      <guid>https://dev.to/ksolomon/unexpected-transformations-a-year-of-growth-through-adversity-500d</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/newyear"&gt;2025 New Year Writing challenge&lt;/a&gt;: Retro’ing and Debugging 2024.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A ruptured tendon in my dominant hand just before Christmas 2023 didn't just derail my coding - it catalyzed an unexpected transformation in my career. Within weeks, I found myself thrust from being 'just another dev' into leading a team of six junior developers, compressing what should have been a gradual transition into a sudden leap.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Crucible of Leadership
&lt;/h2&gt;

&lt;p&gt;The transition from developer to team leader brought countless sleepless nights and moments of self-doubt. What started as a physical limitation became the catalyst for profound professional growth. The most striking challenge wasn't the injury itself, but bridging a 30-year age gap with our youngest team member. Through persistent communication and a commitment to mutual learning, we've cultivated an environment where experience and fresh perspectives complement each other beautifully.&lt;/p&gt;

&lt;p&gt;What began as uncertainty has evolved into a distinctive leadership style, shaped by both successes and setbacks. Our team has developed a culture where questions are encouraged, innovation is celebrated, and growth is constant. The age difference that initially seemed daunting has become one of our greatest strengths, combining decades of industry knowledge with fresh, contemporary approaches to problem-solving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Evolution Against the Odds
&lt;/h2&gt;

&lt;p&gt;Despite the physical limitations, my commitment to hands-on development remained strong. Logging 707 hours of coding time - averaging over two hours daily with just one functional hand - proved that adaptation trumps limitation. This dedication helped maintain credibility with the team while demonstrating that obstacles can become opportunities for innovation.&lt;/p&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.amazonaws.com%2Fuploads%2Farticles%2Ff4xq2el2xgtsge43861d.jpeg" 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.amazonaws.com%2Fuploads%2Farticles%2Ff4xq2el2xgtsge43861d.jpeg" alt="WakaTime Stats" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under our collective leadership, we successfully launched eight new sites, with most beating their deadlines. More significantly, we revolutionized our approach to quality by implementing comprehensive SonarQube testing and establishing strict accessibility standards. Every project now launches with WCAG 2.0 AA compliance as a minimum requirement, not an afterthought.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project That Changed Everything
&lt;/h2&gt;

&lt;p&gt;One particular project became a crucible for growth, though not in the way we expected. A perfect storm of challenges - my injury, an expansive scope, a demanding client, and scope creep - resulted in a five-month delay. While it marked the most challenging period of my career, it also sparked crucial improvements in our processes.&lt;/p&gt;

&lt;p&gt;Instead of deflecting responsibility onto my team, I shouldered the accountability for our setbacks. This decision, though difficult, strengthened team trust and demonstrated the importance of leadership through adversity. The support from upper management during this period revealed that vulnerability in leadership isn't weakness - it's an opportunity for organizational growth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Documentation Renaissance
&lt;/h2&gt;

&lt;p&gt;Moving beyond tribal knowledge became a top priority. We've transformed our documentation from the informal "ask Keith" approach to comprehensive, accessible resources. This shift not only improved our efficiency but created a foundation for sustainable team growth and knowledge sharing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creative Renaissance
&lt;/h2&gt;

&lt;p&gt;Amidst the professional turbulence, an unexpected creative awakening emerged. What began as a simple website redesign project blossomed into a profound artistic journey. A modest six-paragraph story expanded into a 50,000-word narrative, launching me into an unexpected parallel career as a writer. Three additional stories now simmer in development, each offering a different refuge from the demands of technical leadership.&lt;/p&gt;

&lt;p&gt;This creative outlet has become more than just an escape - it's a complementary force that enhances my technical leadership. The storytelling skills have improved my ability to communicate technical concepts, while the creative problem-solving strengthens my approach to coding challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Forward
&lt;/h2&gt;

&lt;p&gt;The year's experiences have shaped a clearer vision for the future. We're continuing to refine our project management practices and documentation standards while exploring new ways to leverage our team's diverse perspectives. The creative writing projects are evolving alongside our technical achievements, creating a satisfying balance between logical and artistic pursuits.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Note of Gratitude
&lt;/h2&gt;

&lt;p&gt;My team's resilience during our challenging projects, their enthusiasm for learning, and their willingness to embrace change have been invaluable. Specific mentors - especially those who guided me through the leadership transition - have profoundly influenced my growth. Their support transformed what could have been a career setback into a launching pad for new opportunities.&lt;br&gt;
As we move into 2025, these experiences have equipped us with stronger processes, clearer communication, and a more cohesive team culture. What started as an injury-induced career pivot has evolved into a journey of unexpected discovery and growth.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>newyearchallenge</category>
      <category>career</category>
    </item>
    <item>
      <title>Memory is a Funny Thing</title>
      <dc:creator>Keith Solomon </dc:creator>
      <pubDate>Mon, 30 Dec 2024 15:56:07 +0000</pubDate>
      <link>https://dev.to/ksolomon/memory-is-a-funny-thing-cop</link>
      <guid>https://dev.to/ksolomon/memory-is-a-funny-thing-cop</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally posted at &lt;a href="https://keithsolomon.net/memory-is-a-funny-thing/" rel="noopener noreferrer"&gt;My Blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Memory is weird. This morning, as I emerged from a vivid dream about my first encounter with what we might call the “proto-internet,” I found myself marveling at how some memories fade within minutes while others resurface with stunning clarity decades later. The dream transported me back to the summer of 1989, when my mother had just begun her undergraduate studies at the University of Southern Mississippi, and I was about to stumble upon a connection that would change my life.&lt;/p&gt;

&lt;p&gt;In those days, I was an outsider, a kid without many friends until fate led me to a group of college students who shared two passions: Dungeons &amp;amp; Dragons and computing. Through them, I discovered my sanctuary in an unlikely place: a small computer lab tucked away on the upper floor of Forrest County Hall. Unlike the other labs scattered across campus with their rows of PCs, this space housed something different—about twenty Wyse terminals with their distinctive green-on-black displays, all connected to a Honeywell Bull mainframe.&lt;/p&gt;

&lt;p&gt;The memory of that space remains remarkably tangible. The constant symphony of cooling fans provided the backdrop, punctuated by the staccato rhythm of the massive dot matrix printer. The air conditioning kept the room cool enough for the equipment, but I remember the warmth of belonging that I found there. Through those tiny screens, I glimpsed a world far bigger than my small Mississippi town could contain.&lt;/p&gt;

&lt;p&gt;What strikes me now is how different those early online interactions were from today’s instant gratification platforms. Everything moved at a more deliberate pace—communication was primarily through email, creating a thoughtful asynchronicity that seems almost foreign in our current age of instant messaging and social media dopamine hits. Each interaction felt more intentional, more precious.&lt;/p&gt;

&lt;p&gt;The screens flickered as my newfound friends typed commands in what seemed like a secret language, each keystroke an invitation into their digital world. I spent countless hours that summer learning their arcane ways, watching the green text scroll across the screen, feeling like I was part of something larger than myself. The memory is so crisp that I can still hear the click-clack of the keyboards and see the monitor glow reflecting off my friends’ focused faces.&lt;/p&gt;

&lt;p&gt;This morning’s unexpected memory has made me contemplate how profoundly the internet has transformed since those early days. What began as a small, intimate community has exploded into a vast, ever-expanding network connecting billions. The access to information and communication we have today would have seemed like science fiction to that wide-eyed kid in the computer lab. Yet with this progress has come a certain loss—the intimacy and simplicity of those early digital connections have been buried under an avalanche of notifications, likes, and shares.&lt;/p&gt;

&lt;p&gt;As I write this on my iPad, I find myself holding two truths simultaneously: a nostalgia for that simpler digital age when computers were tools for connection rather than extensions of our identity, and a deep appreciation for how technology has enriched our lives, enabling us to bridge vast distances and share our stories with the world. Perhaps what I’m really longing for isn’t the technology itself, but the sense of wonder and possibility I felt in that humid Mississippi summer.&lt;/p&gt;

&lt;p&gt;Memory shapes who we are, constantly evolving as we weave new experiences into the tapestry of our past. And while I cherish those formative moments in Forrest County Hall, I’m equally grateful for all the memories—both digital and analog—that have followed. In this ever-shifting landscape of memory and technology, one constant remains: our fundamental need for genuine human connection, whether mediated through green-on-black terminals or high-resolution touchscreens.&lt;/p&gt;

&lt;p&gt;When those old memories surface unexpectedly, they offer us a chance to pause and reflect. They remind us that while technology evolves at a dizzying pace, the core human experience—our desire to connect, to belong, to understand and be understood—remains beautifully unchanged. Memory may be weird, but in its mysterious workings, it reveals the threads that connect our past and present selves, weaving together the story of who we are becoming.&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
  </channel>
</rss>
