<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Development Log]]></title><description><![CDATA[Development Log]]></description><link>https://developmentlog.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/69a3b39fa7428b958d6b34ab/345c05e3-2348-45f1-8951-14288dd21683.jpg</url><title>Development Log</title><link>https://developmentlog.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Sat, 05 Sep 2026 01:24:25 GMT</lastBuildDate><atom:link href="https://developmentlog.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Five things we validate in the browser before sending a photo to an AI video model]]></title><description><![CDATA[When a user uploads a photo to an image-to-video tool, the expensive part happens far away from the browser: a GPU renders for one to five minutes and the credits are spent whether the output is usabl]]></description><link>https://developmentlog.hashnode.dev/five-things-we-validate-in-the-browser-before-sending-a-photo-to-an-ai-video-model</link><guid isPermaLink="true">https://developmentlog.hashnode.dev/five-things-we-validate-in-the-browser-before-sending-a-photo-to-an-ai-video-model</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[XIAOJUN MAO]]></dc:creator><pubDate>Thu, 03 Sep 2026 10:38:55 GMT</pubDate><content:encoded><![CDATA[<p>When a user uploads a photo to an image-to-video tool, the expensive part happens far away from the browser: a GPU renders for one to five minutes and the credits are spent whether the output is usable or not.</p>
<p>That asymmetry is the whole argument for client-side validation. A check that costs 5ms in the browser can save a minute of GPU time and a refund. Here are the five we run on <a href="https://stivio.ai">Stivio</a> before a job is ever queued, and the reasoning behind each.</p>
<h2>1. Format, before anything else</h2>
<p>We accept PNG, JPEG and WebP. Not because the models are picky about containers, but because everything downstream — thumbnailing, EXIF reads, dimension probing — assumes a decodable raster.</p>
<pre><code class="language-js">const ACCEPTED = ['image/png', 'image/jpeg', 'image/webp']

function checkFormat(file) {
  if (!ACCEPTED.includes(file.type)) {
    return { ok: false, reason: 'format' }
  }
  return { ok: true }
}
</code></pre>
<p>One caveat: <code>file.type</code> comes from the OS, not from the bytes. A renamed <code>.txt</code> will happily report <code>image/png</code>. If that matters to you, read the first 12 bytes and check the magic number. We do the cheap check in the browser and the real one server-side, because the browser check is about <em>user feedback speed</em>, not security.</p>
<h2>2. Size, with a number the user can act on</h2>
<p>The limit is 10 MB. What matters more than the number is the error message. "File too large" is useless. "This photo is 24 MB, the limit is 10 MB — try exporting at a smaller size" tells someone what to do next.</p>
<p>Modern phone cameras produce 3–8 MB files, so the limit almost never bites for real photos. The uploads that hit it are usually screenshots of screenshots, or PNG exports of photographs — which brings us to the next check.</p>
<h2>3. Aspect ratio, because the output inherits it</h2>
<p>This is the one most people miss. The generated video keeps the aspect ratio of the source image. There is no crop step, no letterbox. So the framing decision is made at upload time, not at export time.</p>
<pre><code class="language-js">function readDimensions(file) {
  return new Promise((resolve, reject) =&gt; {
    const img = new Image()
    const url = URL.createObjectURL(file)
    img.onload = () =&gt; {
      URL.revokeObjectURL(url)
      resolve({ w: img.naturalWidth, h: img.naturalHeight })
    }
    img.onerror = () =&gt; { URL.revokeObjectURL(url); reject() }
    img.src = url
  })
}
</code></pre>
<p>Two things worth knowing here. <code>URL.revokeObjectURL</code> is not optional — without it, every rejected upload leaks a blob for the lifetime of the tab. And <code>naturalWidth</code> is the decoded pixel width, which is what you want; <code>width</code> reflects CSS layout and will lie to you if the image is in the DOM.</p>
<p>Once you have the ratio, you can tell the user where the output will fit:</p>
<pre><code class="language-js">const RATIOS = [
  { name: '9:16 (Reels, TikTok)', value: 9 / 16 },
  { name: '1:1 (product grid)',   value: 1 },
  { name: '16:9 (YouTube, web)',  value: 16 / 9 },
]

function nearestTarget(w, h) {
  const r = w / h
  return RATIOS.reduce((best, t) =&gt;
    Math.abs(t.value - r) &lt; Math.abs(best.value - r) ? t : best
  )
}
</code></pre>
<p>Telling someone "this will render as 4:3, closest to 1:1 — crop it first if you want a Reel" before they spend credits is worth more than any amount of post-hoc support.</p>
<h2>4. Minimum dimensions, because upscaling shows</h2>
<p>A 200x200 avatar technically passes every check above. It also produces an unusably soft video, because the model animates what it was given. We warn below roughly 512px on the short edge. Not a hard block — someone may genuinely want to animate a small image — but a warning that sets expectations.</p>
<p>The general principle: <strong>block what will fail, warn what will disappoint.</strong> Conflating the two produces either a tool that feels obstructive or one that wastes people's money.</p>
<h2>5. EXIF orientation, the silent one</h2>
<p>JPEGs from phones carry an orientation flag. Browsers respect it when rendering an <code>&lt;img&gt;</code>; many server-side decoders do not. The result is the classic bug where the preview looks upright and the output is rotated 90 degrees.</p>
<p>The fix is to normalise before upload — draw to a canvas, which bakes in the display orientation, and send the canvas output instead of the original bytes:</p>
<pre><code class="language-js">async function normalise(file) {
  const bitmap = await createImageBitmap(file, { imageOrientation: 'from-image' })
  const canvas = document.createElement('canvas')
  canvas.width = bitmap.width
  canvas.height = bitmap.height
  canvas.getContext('2d').drawImage(bitmap, 0, 0)
  return new Promise(res =&gt; canvas.toBlob(res, 'image/jpeg', 0.92))
}
</code></pre>
<p><code>createImageBitmap</code> with <code>imageOrientation: 'from-image'</code> does the rotation for you. Note that this strips all EXIF, including the orientation tag — which is exactly what you want, since the pixels are now already in the right order.</p>
<h2>The part that isn't a check</h2>
<p>None of this validates the <em>prompt</em>, which is where most disappointing outputs actually come from. A sharp, correctly-oriented, well-framed photo with the instruction "make it cool" will still produce something arbitrary.</p>
<p>We ended up putting three labelled fields in front of people instead of one free-text box — what moves, how the camera behaves, the mood — because splitting the question is the cheapest way to get a specific answer. That change did more for output quality than any of the five checks above.</p>
<p>But the checks are still worth having. They are the difference between a user who wasted two minutes and a user who wasted two minutes <em>and</em> some credits.</p>
]]></content:encoded></item><item><title><![CDATA[I Spent Three Weeks Hand-Drawing Architecture Diagrams for My Blog. Then I Stopped.]]></title><description><![CDATA[For about three weeks last November, my evenings looked the same. I'd finish writing a technical post, lean back, and realize the hardest part hadn't even started yet: the diagram.
I write a small eng]]></description><link>https://developmentlog.hashnode.dev/i-spent-three-weeks-hand-drawing-architecture-diagrams-for-my-blog-then-i-stopped</link><guid isPermaLink="true">https://developmentlog.hashnode.dev/i-spent-three-weeks-hand-drawing-architecture-diagrams-for-my-blog-then-i-stopped</guid><dc:creator><![CDATA[XIAOJUN MAO]]></dc:creator><pubDate>Wed, 03 Jun 2026 01:40:10 GMT</pubDate><content:encoded><![CDATA[<p>For about three weeks last November, my evenings looked the same. I'd finish writing a technical post, lean back, and realize the hardest part hadn't even started yet: the diagram.</p>
<p>I write a small engineering blog. Nothing huge, around 2,400 monthly readers, mostly developers who land on my posts about message queues and caching layers from a Google search. The writing comes easy to me. The diagrams never did.</p>
<h2>The part nobody warns you about</h2>
<p>My setup was the usual one. I'd open draw.io in one tab, keep my notes in another, and start dragging rectangles around a canvas. A simple three-service diagram with a load balancer, two app servers, and a Postgres instance would take me 40 to 50 minutes. Not because the architecture was complex, but because I'm not a designer. I'd spend ten minutes just trying to make the arrows line up so they didn't cross each other like spaghetti.</p>
<p>The post I remember most clearly was one I published on November 14th about event-driven systems. I'd written the whole thing in about two hours on a Saturday morning at a coffee shop near my apartment in Lisbon, the one on Rua da Prata that does a decent flat white. The writing was done by 11am. The diagram took me until almost 2pm. Three hours for one picture of a Kafka topic feeding three consumers. I closed my laptop genuinely annoyed at myself.</p>
<p>And here's the thing that really got to me: my diagrams looked like everyone else's. The same gray boxes, the same blue cylinders for databases, the same stock AWS icons that show up in roughly half the infrastructure posts on the internet. Readers would scroll past them. I could tell from my analytics that the diagrams weren't where people stopped. They stopped on the code blocks.</p>
<h2>The accidental fix</h2>
<p>I wasn't looking for a tool. I found it because a friend in my old Berlin meetup group, Marek, dropped a link in our group chat with the message "this saved my last three posts." It was <a href="https://architecturediagramai.com/">Architecture Diagram AI</a>, and honestly I almost ignored it because I assumed it would be another generic diagram-maker with a free tier that does nothing.</p>
<p>I tried it the next morning. The pitch is simple enough that I was skeptical: you describe the architecture in plain text, pick a visual style, and it generates an actual image. So I typed in something like "a load balancer routing to two Node servers, both talking to a shared Redis cache and a Postgres database." I picked a style that matched the blue-and-orange palette I use on my blog. About fifteen seconds later I had a PNG.</p>
<p>It wasn't the gray-box thing. It was a clean, genuinely good-looking visual that looked like something a design team would have made, not a tired developer at 1am. The first time it generated something usable, I actually said "oh" out loud in my empty kitchen.</p>
<h2>What changed in the numbers</h2>
<p>I'm a numbers person, so I tracked this. Over the next two weeks I published four posts, and I used <a href="https://architecturediagramai.com/">the AI architecture diagram generator</a> for the visuals in all of them. My average time-per-diagram dropped from roughly 45 minutes to under 5. That's not a rounding error. Across those four posts, that's something like two and a half hours I got back, which for someone who blogs around their actual job is a real amount of time.</p>
<p>The part I didn't expect was the engagement shift. My average time-on-page went from about 2 minutes 50 seconds to 3 minutes 40 seconds over that stretch. Correlation isn't causation and I'm not going to pretend four posts is a real sample size, but the diagrams stopped being the thing people skipped. One reader even emailed me to ask what tool I used for "the graphics," which had literally never happened in two years of blogging.</p>
<p>The workflow that stuck for me is boring in a good way. I write the post first, all of it. Then I read back through and wherever I think "a picture would help here," I describe the system in one sentence, generate the image, download the PNG, and drop it straight into my CMS. No exporting, no fiddling with SVG settings, no fighting with arrow alignment. The download is a clean PNG that just works wherever I paste it.</p>
<h2>A small thing that mattered more than I expected</h2>
<p>There's a detail I keep coming back to. Before this, the diagram step had a way of derailing my whole publishing rhythm. I'd finish writing on a Saturday, hit the diagram wall, get frustrated, and tell myself I'd "just do the picture tomorrow." Tomorrow would become next weekend. I had three finished drafts sitting unpublished in October purely because I didn't have the energy to make their diagrams. Two of them I never published at all.</p>
<p>When the diagram stopped being a two-hour chore and became a two-minute one, that backlog problem just evaporated. In December I published six posts, which is more than I'd managed in the previous two months combined. The tool didn't make me a better writer. It removed the specific bit of friction that was quietly killing my consistency, and consistency is most of what blogging actually rewards.</p>
<h2>The honest caveats</h2>
<p>It's not magic. For one genuinely weird microservices setup with about eleven services and a couple of circular dependencies, I still ended up sketching it by hand because I couldn't describe it cleanly in text. If you can't write the architecture in a sentence or two, you're going to struggle to generate it. And the styles, while good, are styles, so if your blog has a very specific brand look you might find the match isn't perfect every time.</p>
<p>But for the 90% of diagrams I actually make, the ones with a handful of boxes and some arrows showing how data flows, it's replaced my entire old process. I haven't opened draw.io in over a month.</p>
<h2>Would I recommend it?</h2>
<p>If you write technical content and you've ever felt that specific dread of finishing the words only to face the diagram, yes. I went in skeptical and I'm the kind of person who churns through tools and abandons them after a week. This one stuck. You can try it yourself at <a href="https://architecturediagramai.com/">architecturediagramai.com</a> — you get a free diagram after signing in with Google, which is exactly how I tested whether it was real before I trusted it with a published post.</p>
<p>I still write at that same coffee shop on Rua da Prata most Saturdays. The flat white is still good. The difference is I'm out the door by noon now instead of fighting arrows until the afternoon.</p>
]]></content:encoded></item><item><title><![CDATA[Why I Spent a Month Teaching an AI to Read Floor Plans]]></title><description><![CDATA[If you've read my previous posts, you know I have a habit of stumbling into weekend projects that turn into month-long obsessions. This one started, as most of them do, with me complaining about somet]]></description><link>https://developmentlog.hashnode.dev/why-i-spent-a-month-teaching-an-ai-to-read-floor-plans</link><guid isPermaLink="true">https://developmentlog.hashnode.dev/why-i-spent-a-month-teaching-an-ai-to-read-floor-plans</guid><dc:creator><![CDATA[XIAOJUN MAO]]></dc:creator><pubDate>Fri, 15 May 2026 01:41:17 GMT</pubDate><content:encoded><![CDATA[<p>If you've read my previous posts, you know I have a habit of stumbling into weekend projects that turn into month-long obsessions. This one started, as most of them do, with me complaining about something that should have been easier than it was.</p>
<p>My sister had just bought her first apartment and asked me — the "tech guy" in the family — to help her visualize moving some walls. She sent me a phone photo of the listing's floor plan, half-blurry, slightly rotated, and asked if I could just "drag the walls around" for her. I assumed there would be a quick web tool for this. There wasn't. At least not one that didn't require an account, a tutorial, and roughly forty minutes of frustration before producing anything useful.</p>
<p>So I did what I always do. I opened a blank repo, made a coffee, and started typing.</p>
<h2>Figuring Out What "Reading" a Floor Plan Even Means</h2>
<p>The first wall I hit (pun intended) was that floor plans are deceptively hard for computers. Humans look at one and instantly see: this is a wall, this is a door swinging this way, this is a window, that little arc is a toilet. A model just sees a bunch of black lines on a white background.</p>
<p>I spent the first week just collecting samples — old apartment listings, blueprints I'd saved for various reasons, hand-drawn sketches from a Reddit thread — and trying to figure out what consistent visual patterns existed across all of them. The answer, frustratingly, was "not many." Different drafters use different conventions. Some plans label rooms, some don't. Some are to scale, some are vibes.</p>
<p>I ended up building a small pipeline that did three things in sequence: detect the outer boundary of the plan, segment the interior into rooms, and then classify the symbols inside each room. None of these steps were novel on their own — there's plenty of academic work on each piece — but stitching them together so the output was useful to a non-technical person turned out to be the actual hard part.</p>
<h2>The Embarrassing First Demo</h2>
<p>The first version I showed my sister was, in her exact words, "kind of horrible." It correctly identified the walls but thought her bathtub was a sofa. It missed two doors entirely. It rotated the plan 90 degrees for reasons I still don't fully understand.</p>
<p>But — and this is the part that kept me going — it got the rooms right. The living room was the living room. The kitchen was the kitchen. That meant the underlying segmentation was working; I just had bad symbol recognition on top of it.</p>
<p>I retrained the symbol classifier on a much bigger dataset, added a step that re-orients the plan based on detected text labels, and gave it the ability to ask the user to confirm ambiguous detections instead of just guessing. That last bit alone improved the perceived quality enormously. People are way more forgiving when a tool says "I think this is a door — yes or no?" than when it silently gets it wrong.</p>
<h2>Where the Project Stopped Being a Toy</h2>
<p>Around week three, I realized the tool was actually useful for something my sister hadn't even asked about: redesign. Once the plan was parsed into structured data — rooms, walls, doors, fixtures — I could let her drag things around, add new walls, swap fixtures, and re-render the result in seconds. I added a simple 3D preview because I wanted to see if it was possible, and it turned out to be the feature she used the most.</p>
<p>She walked her partner through their potential renovation on a video call by sharing the 3D view. He spotted that the new kitchen island would block the only path to the balcony. They changed the plan. I never would have caught that on a 2D drawing, and neither would they.</p>
<p>That was the moment the project stopped feeling like a tech demo and started feeling like a product.</p>
<h2>The Boring Stuff That Took Forever</h2>
<p>People always ask me what the hard part of a side project is, and the honest answer is never the part you'd expect. For this one, it wasn't the ML. It was:</p>
<ul>
<li>File uploads. Specifically, handling the wild variety of formats people throw at a floor plan tool. JPEGs from phones. PDFs scanned at strange angles. Screenshots from listing sites with watermarks. I spent an embarrassing amount of time on a preprocessing step that just tries to find the actual plan inside a noisy image.</li>
<li>Units. Some plans are in meters, some in feet, some in pixels with no scale reference at all. Letting the user click two points and enter a known dimension to set the scale ended up being one of the most-used features.</li>
<li>Export. Nobody wants a plan trapped in a web app. Getting clean PNG, PDF, and a basic DXF export working took me longer than the entire 3D renderer.</li>
</ul>
<p>None of this is glamorous. None of it shows up in a demo video. But it's the difference between "neat hack" and "thing my sister actually uses."</p>
<h2>What I Learned</h2>
<p>A few takeaways from the past month, in no particular order. Start with one real user — not an imagined market segment, but a specific person whose problem you keep poking at. The feedback loop is immediate and honest. When that real user is also a family member, the feedback is even more honest, sometimes painfully so.</p>
<p>Ship the ugly version. My first demo was rough, but showing it to my sister forced me to confront which parts genuinely mattered and which were vanity polish. I would have spent another two weeks on irrelevant details otherwise.</p>
<p>Spend disproportionate time on the unglamorous edges. The model is the headline, but the file handling, the unit calibration, and the export formats are what make people stick around.</p>
<p>If you want to play with what I ended up building, it's live at <a href="https://floorplanai.net/">floor plan AI</a>. Bring a messy phone photo of a floor plan and see how it does — I'd genuinely love to hear where it stumbles, because I'm still actively improving the symbol classifier and the edge cases are where the interesting bugs live.</p>
<p>Next weekend I'm probably going to try wiring up a "furniture suggestion" mode, where the tool proposes a layout based on the room dimensions and the user's stated preferences. I have no idea if it'll work. That's usually a good sign.</p>
]]></content:encoded></item><item><title><![CDATA[I Built Three Calculator Tools Over the Weekends — Here's What I Learned]]></title><description><![CDATA[So I've been doing a lot of side projects lately — mostly small, focused tools that solve one specific problem and do it well. Over the past few months, I ended up building three separate calculator a]]></description><link>https://developmentlog.hashnode.dev/i-built-three-calculator-tools-over-the-weekends-here-s-what-i-learned</link><guid isPermaLink="true">https://developmentlog.hashnode.dev/i-built-three-calculator-tools-over-the-weekends-here-s-what-i-learned</guid><dc:creator><![CDATA[XIAOJUN MAO]]></dc:creator><pubDate>Mon, 13 Apr 2026 09:15:07 GMT</pubDate><content:encoded><![CDATA[<p>So I've been doing a lot of side projects lately — mostly small, focused tools that solve one specific problem and do it well. Over the past few months, I ended up building three separate calculator apps during weekends and late evenings after my day job. I wanted to write up what that experience was like, not from a "look how amazing I am" angle, but more like... the real messy process of going from "this would be useful" to actually shipping something.</p>
<p>If you're a developer who's been sitting on a side project idea, maybe this will either motivate you or at least make you feel better about your own chaos.</p>
<h2>Why Calculator Tools?</h2>
<p>Honestly, calculators came up kind of by accident. A friend of mine was trying to figure out his monthly car payments and was complaining that every website he visited was either covered in ads, asked him to sign up before showing results, or gave him numbers that didn't seem right. He literally texted me like, "bro can you just make a clean one?"</p>
<p>That's how it started. One weekend, I opened VS Code, picked a stack I was comfortable with (React + a bit of vanilla CSS, nothing fancy), and started building. The goal was simple: a fast, no-login, no-nonsense tool that gives you the answer immediately.</p>
<p>That first project turned into the <a href="https://carpaymentcalculator.app/">Car Payment Calculator</a>, and shipping it taught me more about building focused web tools than any tutorial I'd followed.</p>
<h2>The Technical Side: Keeping It Simple on Purpose</h2>
<p>One mistake I used to make with side projects was over-engineering them. I'd spend three weekends setting up the "perfect" architecture and then lose motivation before building the actual feature. This time, I forced myself to keep things minimal.</p>
<p>For each calculator, the rules I set for myself were:</p>
<ul>
<li>No backend unless absolutely necessary</li>
<li>Results render instantly without any page reload</li>
<li>Mobile-first layout from day one</li>
<li>Accessible inputs (labels, keyboard navigation, readable font sizes)</li>
</ul>
<p>The math logic itself is the easy part — it's mostly just standard formulas. The harder part is the UX: what happens when a user enters 0? What if they clear a field? What's the tab order? Do the inputs feel natural on a phone keyboard?</p>
<p>I spent way more time on edge cases and input validation than on the core calculation logic. That's just how it goes with form-heavy interfaces.</p>
<h2>The Second Project: Percentages Gave Me a Headache</h2>
<p>After shipping the car payment tool, I had the itch to build another one. I kept seeing people (including myself) fumbling with percentage calculations in spreadsheets or reaching for their phone calculator and doing it in multiple steps.</p>
<p>The thing about percentage calculations is they sound simple but there are actually several different things people mean when they say "calculate the percentage." Do they mean percentage of a number? Percentage difference? Percentage change over time?</p>
<p>I ended up focusing on the growth/change use case specifically — the kind of calculation you reach for when you're comparing two numbers and want to know how much something changed. That became the <a href="https://percentageincreasecalculator.app/">Percentage Increase Calculator</a>.</p>
<p>Building this one, I got more intentional about the input UX. I added clear labels explaining what each field meant, and I made sure the result explained itself — not just showing a number, but showing the formula breakdown so users could verify the math themselves. That transparency thing matters more than I expected. People actually trust tools more when they can see the work.</p>
<h2>Dealing With SEO as a Solo Developer</h2>
<p>Here's something nobody really tells you when you're building small tools: getting found is hard. You can ship the cleanest, fastest, most useful calculator on the internet and it will sit at zero traffic for months if you don't think about SEO at all.</p>
<p>I'm not an SEO expert by any stretch. But I've picked up a few things just from trial and error:</p>
<p><strong>Page speed matters a lot.</strong> Google cares about Core Web Vitals now, and lightweight tools have a natural advantage here if you don't bloat them with unnecessary JavaScript. Keep your bundles small, lazy-load what you don't need immediately, and don't import a 200KB library when a 10-line function does the job.</p>
<p><strong>The title and meta description are still important.</strong> Like, embarrassingly important for such basic stuff. I spent time writing accurate, specific titles that match what someone would actually type into a search bar.</p>
<p><strong>Internal structure.</strong> Even for a single-page tool, having a proper H1, clear descriptive text around the calculator, and a logical content flow helps crawlers understand what the page is actually about.</p>
<p><strong>Backlinks from real content.</strong> This is the long game, but writing about what you built (like this post) does actually help. Not overnight, but over time.</p>
<h2>The Third One: A Longer Build With More Math</h2>
<p>The third calculator I built was more complex than the first two. I wanted to tackle something that involved compound growth calculations over time — the kind of thing where you're projecting numbers out over many years with different variables.</p>
<p>Without getting into the specifics of the domain, the technical challenge was interesting: how do you display long-term projection data in a way that's readable without overwhelming users?</p>
<p>I ended up going with a combination of a summary output and an expandable year-by-year table. Users get the headline number immediately, and if they want to dig into the breakdown, it's there. That pattern — summary first, detail on demand — is something I've started applying to other UI work too.</p>
<p>That project is the <a href="https://rothiracalculator.app/">Roth IRA Calculator</a>. The math model behind it took me a few iterations to get right, and I had a couple of late nights going through edge cases around contribution limits and partial-year scenarios.</p>
<h2>What I'd Do Differently</h2>
<p>Looking back, here are the things I'd change:</p>
<p><strong>Start with the mobile layout.</strong> I said mobile-first but I didn't always practice it. Retrofitting a desktop layout to work on mobile is always more painful than building mobile-first and expanding up.</p>
<p><strong>Write the meta/SEO content before you ship.</strong> I kept treating this as an afterthought. Now I write the title, description, and a short paragraph of page context before I even start coding. It helps me stay focused on what the tool is actually for.</p>
<p><strong>Test with real users earlier.</strong> I have a bad habit of polishing in private for too long. Even showing a rough prototype to two or three people catches way more issues than another solo review session.</p>
<p><strong>Don't skip accessibility.</strong> I got lazy on keyboard navigation on my first project and had to go back and fix it. Screen reader support and keyboard usability are not hard to add if you build them in from the start — but they're annoying to retrofit.</p>
<h2>The Satisfaction of Shipping Small Things</h2>
<p>There's something genuinely satisfying about shipping a small, focused tool that works exactly as advertised. No accounts, no subscriptions, no dark patterns. Just: user comes in, enters some numbers, gets an answer, leaves.</p>
<p>I've had a few people reach out through the contact forms on these tools saying things like "I've been looking for something this simple for years." That kind of feedback hits different than likes on social media.</p>
<p>If you've been thinking about building a small utility tool, I'd encourage you to just start. Pick one specific problem. Build the minimal version. Ship it. Then iterate.</p>
<p>The tech stack doesn't matter that much. The polish can come later. What matters is that the core thing works and someone can actually use it.</p>
<p>That's pretty much everything I've been up to on the side project front. If you've built something similar or have questions about any of the technical decisions I made, drop them in the comments — happy to talk through it.</p>
]]></content:encoded></item><item><title><![CDATA[The Side Projects That Changed How I Work: My Go-To Free Tools]]></title><description><![CDATA[I still remember the weekend I decided to stop waiting for the "perfect" time to build something.
It was a Saturday afternoon. I had three browser tabs open, a half-eaten bowl of noodles next to my ke]]></description><link>https://developmentlog.hashnode.dev/the-side-projects-that-changed-how-i-work-my-go-to-free-tools</link><guid isPermaLink="true">https://developmentlog.hashnode.dev/the-side-projects-that-changed-how-i-work-my-go-to-free-tools</guid><dc:creator><![CDATA[XIAOJUN MAO]]></dc:creator><pubDate>Sun, 29 Mar 2026 08:23:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69a3b39fa7428b958d6b34ab/3521d9ba-38e8-4edc-8a44-e69393237d66.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I still remember the weekend I decided to stop waiting for the "perfect" time to build something.</p>
<p>It was a Saturday afternoon. I had three browser tabs open, a half-eaten bowl of noodles next to my keyboard, and an idea I had been sitting on for months. I wanted to build small, useful tools — the kind of apps that solve one problem really well and don't require a login to use.</p>
<p>Over the past year, I've shipped four of them. Each one came from a real frustration I had — or that someone close to me had. Here's the story behind each one, and why I'm genuinely proud of what they've become.</p>
<h2>The invoice problem that drove me crazy</h2>
<p>A friend of mine does freelance design work. Every time she finished a project, she'd spend 20–30 minutes manually editing an invoice template in Word, fighting with table alignment and font sizes. "There has to be a better way," she told me one evening over coffee.</p>
<p>That conversation stuck with me. A few weeks later, I built <a href="https://invoicegenerator.run/">Invoice Generator</a> — a dead-simple tool that lets you fill in your details, add line items, and download a clean PDF invoice in under a minute. No account needed. No subscription. Just open it and go. My friend uses it every week now, and honestly, that's all the validation I needed.</p>
<h2>Graph paper — yes, really</h2>
<p>This one surprised me. I was sketching out a UI layout the old-fashioned way — on paper — and realized I didn't have any graph paper at home. I searched online for a printable version and ended up wading through sketchy ad-filled sites just to print a grid.</p>
<p>So I built <a href="https://printablegraphpaper.app/">Printable Graph Paper</a>. You choose your grid size, line color, and paper format, then hit print. Clean, fast, no ads. It took me a weekend to build but I use it almost every week. Sometimes the simplest tools are the most satisfying to make.</p>
<h2>Sudoku for my dad</h2>
<p>My dad loves Sudoku. He's the kind of person who prefers doing puzzles on paper rather than on a phone screen. He used to buy puzzle books regularly, but complained they ran out too fast. When I visited home during a holiday, I watched him flip through the last few pages of his book with a sigh.</p>
<p>I built <a href="https://sudokuprintable.me/">Sudoku Printable</a> for him. It generates unique puzzles at different difficulty levels and formats them nicely for printing. I printed out a stack of 20 puzzles and left them on his desk before I flew back. He called me a week later to ask for more. That phone call meant more to me than any metrics dashboard ever could.</p>
<h2>Times tables, because school is hard</h2>
<p>The last one came from a conversation in a developer forum. Someone mentioned their kid was struggling with multiplication and they wished there was a nice printable times table they could stick on the wall. A few people chimed in saying the same thing.</p>
<p>I built <a href="https://multiplicationchartprintable.app/">Multiplication Chart Printable</a> that same evening. Clean layout, color-coded rows, print-ready. It's the kind of thing that takes one evening to ship but might help a kid somewhere actually enjoy math a little more. I find that thought genuinely motivating.</p>
<h2>What I've learned from building these</h2>
<p>Side projects don't have to be ambitious to be meaningful. The best ones solve a specific, annoying problem for a real person. They ship fast, stay focused, and don't ask anything from the user upfront.</p>
<p>If you're a developer sitting on an idea right now — build it. Start this weekend. It doesn't need to be perfect. It just needs to exist.</p>
]]></content:encoded></item><item><title><![CDATA[The Magic of git clone: How I Built My Second AI App in a Weekend]]></title><description><![CDATA[Remember how I said my first web app was held together by digital duct tape and sheer willpower? Well, it turns out that duct tape is surprisingly strong.
After surviving the absolute nightmare of lea]]></description><link>https://developmentlog.hashnode.dev/the-magic-of-git-clone-how-i-built-my-second-ai-app-in-a-weekend</link><guid isPermaLink="true">https://developmentlog.hashnode.dev/the-magic-of-git-clone-how-i-built-my-second-ai-app-in-a-weekend</guid><dc:creator><![CDATA[XIAOJUN MAO]]></dc:creator><pubDate>Wed, 04 Mar 2026 02:29:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69a3b39fa7428b958d6b34ab/2be16f94-c80c-4918-a314-a572bd656fd1.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Remember how I said my first web app was held together by digital duct tape and sheer willpower? Well, it turns out that duct tape is surprisingly strong.</p>
<p>After surviving the absolute nightmare of learning backend logic the hard way and finally getting my video tool stable, I had an epiphany. I was looking at my messy, hard-fought codebase and realized something magical: I hadn't just built an app. I had accidentally built a reusable template.</p>
<p>I already had the user authentication, the database routing, the payment gateway, and the server architecture all wired up. The infrastructure was sitting right there, begging to be used for something else.</p>
<p>I decided I wanted to pivot and build something I genuinely geek out about. I've always been heavily involved in the e-commerce and affiliate marketing space, and lately, I’ve been completely obsessed with the mechanics of generating images with AI. Specifically, I love the magic of taking rough concepts or basic sketches and rendering them into high-end, hyper-realistic product photos. It’s a massive pain point—so many sellers struggle to get crisp, professional studio shots without blowing their entire budget on a photographer.</p>
<p>So, I opened my terminal and typed <code>git clone</code>.</p>
<p>I cannot even describe the intoxicating feeling of spinning up a new local environment and having 80% of the hard work already done. No more crying over CORS errors at 3 AM. No more agonizing over how to hash passwords. This time, I felt like an actual developer.</p>
<p>All I had to do was rip out the heavy video rendering engine and meticulously wire up some cutting-edge image generation models. I tweaked the UI, optimized the prompts under the hood specifically for e-commerce needs, and focused entirely on making the output look like it came from a professional product studio.</p>
<p>The development process was incredibly fast. What took me months of panic the first time around only took me a couple of highly caffeinated weekends this time.</p>
<p>I successfully launched my passion project. If you are an online seller tired of paying through the nose for basic product photography, I built exactly what you need. You can try out my new <a href="https://amazonaiimagegenerator.com/">Amazon AI Image Generator</a> and see what my hard-earned "duct-tape framework" is truly capable of when pointed at a real-world problem.</p>
<p>It’s wild how much easier the development journey gets once you survive that first massive hurdle. Honestly, now I’m just staring at my code wondering what other tools I can spin up next.</p>
]]></content:encoded></item><item><title><![CDATA[Built on Duct Tape and Panic: The True Story Behind My First Web App]]></title><description><![CDATA[If you told me three months ago that I’d be sacrificing my weekends and surviving purely on instant ramen to build a web app, I would have called you crazy. Back then, I was still struggling to figure]]></description><link>https://developmentlog.hashnode.dev/built-on-duct-tape-and-panic-the-true-story-behind-my-first-web-app</link><guid isPermaLink="true">https://developmentlog.hashnode.dev/built-on-duct-tape-and-panic-the-true-story-behind-my-first-web-app</guid><dc:creator><![CDATA[XIAOJUN MAO]]></dc:creator><pubDate>Wed, 04 Mar 2026 02:21:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/69a3b39fa7428b958d6b34ab/633e0802-d190-4d68-9675-630083c11a9c.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you told me three months ago that I’d be sacrificing my weekends and surviving purely on instant ramen to build a web app, I would have called you crazy. Back then, I was still struggling to figure out how to vertically center a div without breaking my entire layout.</p>
<p>The whole idea started because I was broke. I wanted to make some faceless short videos for social media, but every tool out there either required a PhD in video editing or cost a ridiculous monthly subscription. In a moment of pure, unadulterated beginner arrogance, I thought to myself: <em>“How hard can it be? I’ll just build my own. It’ll take like, what, two weeks?”</em></p>
<p>Oh, the innocence.</p>
<p>The first week was actually fun. I followed a couple of YouTube tutorials, set up a basic React frontend, and felt like a coding god. But the moment I tried to connect the actual video rendering logic to the backend, my world absolutely crumbled.</p>
<p>My first attempt at a rendering queue was a disaster. If two people clicked "generate" at the same time, the server would literally panic, freeze for twenty minutes, and then spit out an audio file with no video. I was paying for cloud hosting, but watching my usage limits spike because of infinite loops in my spaghetti code felt like watching my wallet catch on fire.</p>
<p>The lowest point hit around week five. I had spent three entire days staring at a red <code>CORS policy</code> error in my browser console. I didn't even know what CORS meant. I was pasting my code into every developer forum I could find, getting roasted by senior devs for my terrible database structure. One night, at 3 AM, my local environment crashed so hard it corrupted my database. I sat on my bedroom floor, staring at a black screen, completely defeated. I hovered my mouse over the "Delete Repository" button on GitHub. I was done. It was too hard.</p>
<p>But right before I clicked it, my roommate walked in. He had the link to my incredibly janky, half-broken testing environment. "Hey man," he said, "that weird site you're making? I just used it to make a promo for my local band. It took like five minutes to load, but it actually worked. It looks sick."</p>
<p>I froze. He actually used it? And it didn't crash?</p>
<p>That tiny sliver of validation was all it took. I didn't delete the repo. Instead, I drank an unhealthy amount of black coffee and spent the next 48 hours completely rewriting my backend. I learned about asynchronous tasks, I figured out how webhooks actually function, and I finally—finally—killed that stupid CORS error.</p>
<p>It was ugly, painful, and honestly, the code is still probably held together by digital duct tape and sheer willpower. But it’s alive.</p>
<p>Today, it is actually out there in the wild. If you want to see the result of my endless frustration, late-night panic attacks, and hundreds of StackOverflow searches, you can try the <a href="https://aiugcvideogen.com/">AI UGC Video Generator</a> for yourself.</p>
<p>It might not be perfect, and I’m definitely still learning how to be a "real" developer. But every time I check the database and see that a stranger on the internet successfully generated a video using something I built from scratch? Best feeling in the world.</p>
<p>Would I do it again? Absolutely. But maybe next time, I'll read the API documentation before I start writing code.</p>
]]></content:encoded></item></channel></rss>