<?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: Scott Steinmetz</title>
    <description>The latest articles on DEV Community by Scott Steinmetz (@scott_steinmetz).</description>
    <link>https://dev.to/scott_steinmetz</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%2F4050394%2F611c58d9-5498-4ab0-a85f-b1e3a2e49097.png</url>
      <title>DEV Community: Scott Steinmetz</title>
      <link>https://dev.to/scott_steinmetz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/scott_steinmetz"/>
    <language>en</language>
    <item>
      <title>A Digital Toolbox for Seven Locations (and Every Truck)</title>
      <dc:creator>Scott Steinmetz</dc:creator>
      <pubDate>Tue, 11 Aug 2026 14:00:02 +0000</pubDate>
      <link>https://dev.to/scott_steinmetz/a-digital-toolbox-for-seven-locations-and-every-truck-1141</link>
      <guid>https://dev.to/scott_steinmetz/a-digital-toolbox-for-seven-locations-and-every-truck-1141</guid>
      <description>&lt;p&gt;I'm the only maintenance person for seven business locations. A dealership, a parts warehouse, a body shop, and five separate auto parts stores, plus the service trucks that move between them. When something breaks, I'm the one who gets the call, no matter which of the seven sites it's at.&lt;/p&gt;

&lt;p&gt;The calls used to come in however people felt like sending them. A text to my personal phone. A verbal "hey, when you get a second" in the parking lot. A voicemail with no callback number. Nothing was written down anywhere, so nothing could be tracked, prioritized, or handed off. If I forgot a request, there was no record that it ever happened.&lt;/p&gt;

&lt;p&gt;The supply side was just as loose. I'd show up to fix a light fixture and discover I was out of the right bulbs, because the only inventory system was my memory of what I thought was still in the truck. Off-the-shelf work order software didn't fix either problem. That kind of software is built for facilities teams with a dozen technicians and a training budget, not a solo operation covering seven addresses. None of it treated a service truck as a real location with its own stock on the shelf, which is exactly what I needed.&lt;/p&gt;

&lt;p&gt;It was actually my wife who called it. She'd hear me on the phone with yet another location, watch me try to reconstruct what was still on the truck from memory, and finally pointed out the obvious: I build exactly this kind of system for other businesses, so why was I running mine out of my head? She was right. So I built it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the System Works
&lt;/h2&gt;

&lt;p&gt;So I built the tool myself, sized for the job I actually have.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Report a Problem, No Account Needed:&lt;/strong&gt; Anyone at any of the seven locations can flag an issue from their phone or a store computer in seconds. No username, no password, no app to download first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One Dashboard For Everything:&lt;/strong&gt; Every request from every site lands in a single place I check, instead of six inboxes and a stack of sticky notes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reminders Before Things Break:&lt;/strong&gt; The system tracks routine maintenance on a schedule and automatically opens a reminder the day it's due, so upkeep happens on a calendar instead of only after something fails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Real Supply Shelf for Every Location — and Every Truck:&lt;/strong&gt; Common parts and supplies are tracked location by location, and the truck counts as its own location with its own running count. I always know what's on hand and what's not, before I'm standing in front of the broken fixture.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overcoming the Friction
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Making the Truck a Real Location Without Confusing the Front Desk
&lt;/h3&gt;

&lt;p&gt;Trucks needed the same inventory tracking as a fixed store: a running count, a reorder point, a history of what was used and when. But I didn't want a store employee reporting a broken light and seeing "Truck" sitting in the same dropdown as their own building, wondering if they picked the wrong one.&lt;/p&gt;

&lt;p&gt;I split the two views apart. The public report form only shows the seven physical locations, so nobody's guessing. Behind the scenes, the truck is a full-fledged location with its own shelf of supplies, visible to me on the inventory side where it belongs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Killing Alert Fatigue Before It Started
&lt;/h3&gt;

&lt;p&gt;The moment I started loading in real supply counts, half of them were already below where I'd eventually want a reorder alert, simply because I was entering historical numbers, not fresh restocks. If the system fired a low-stock email for every one of those on day one, I'd have learned to ignore my own alerts within a week.&lt;/p&gt;

&lt;p&gt;I built the alert to only fire when a count crosses down below the line from a healthy level. Loading in a starting number that happens to be low stays silent. An actual drop from full to low sends an email. That distinction keeps the alerts meaningful instead of becoming noise I tune out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tying Every Part to the Job That Used It
&lt;/h3&gt;

&lt;p&gt;A supply count by itself doesn't answer the question that actually matters: where did it go? I wanted every change in stock, whether it's a restock, a manual correction, or a part pulled for a specific repair, to leave a record tied back to the ticket or the routine maintenance job it belonged to. Now when a location's supply count drops, there's always a paper trail explaining why, not just a number that changed for no visible reason.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Business Win
&lt;/h2&gt;

&lt;p&gt;The real measure of this project is how much of my day it gives back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No More Phone Tag:&lt;/strong&gt; Every one of the seven locations reports issues the same way, and every issue lands in one place I actually check, instead of scattered texts and hallway conversations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fewer Wasted Trips:&lt;/strong&gt; Knowing what's stocked on the truck and at each site before I head out means fewer mid-job runs back to the shop for a part I assumed I had.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Shelf That Manages Itself:&lt;/strong&gt; Reorder alerts only fire when something genuinely needs attention, so restocking is a five-minute glance instead of a manual count across seven locations and a truck.&lt;/p&gt;

&lt;p&gt;Next up is connecting the two halves directly: when a repair ticket calls for a part, pulling it straight from the right location's shelf automatically, instead of me doing that math by hand.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>productivity</category>
      <category>api</category>
    </item>
    <item>
      <title>Building a Free Communication Platform for People Who Need It Most</title>
      <dc:creator>Scott Steinmetz</dc:creator>
      <pubDate>Sat, 08 Aug 2026 14:00:02 +0000</pubDate>
      <link>https://dev.to/scott_steinmetz/building-a-free-communication-platform-for-people-who-need-it-most-28g8</link>
      <guid>https://dev.to/scott_steinmetz/building-a-free-communication-platform-for-people-who-need-it-most-28g8</guid>
      <description>&lt;p&gt;For most people, communication is effortless. You think of something, and the words come out. For millions of people, that connection is broken — not because the thinking isn't there, but because the body doesn't cooperate. A child with autism who understands everything said to them but cannot form spoken words. An adult who survived a stroke with their mind intact but their speech gone. A person with ALS watching their voice disappear while their thoughts stay sharp. These are not edge cases. The CDC estimates 1 in 36 children in the United States is diagnosed with autism. Over 795,000 Americans have a stroke every year. Hundreds of thousands more live with conditions that affect speech. For all of them, the ability to communicate — to say "I'm in pain," "I'm hungry," "I love you" — depends on the right tools being available and affordable.&lt;/p&gt;

&lt;p&gt;The commercial AAC market has one serious problem: those tools cost a fortune.&lt;/p&gt;

&lt;p&gt;AAC — Augmentative and Alternative Communication — is a catch-all term for any tool that helps someone communicate when speech alone is not reliable or possible. That includes dedicated voice output devices, symbol-based communication boards, and apps that speak words aloud when a user taps them. Dedicated AAC devices from major manufacturers run $6,000 to $8,000. The top-rated apps on the App Store cost $150 to $300 upfront — before any subscription. Schools and clinics buying licenses for a classroom of non-verbal students are looking at tens of thousands of dollars a year, with most of that money flowing to three or four companies that dominate the market.&lt;/p&gt;

&lt;p&gt;Meanwhile, a parent whose child has autism needs something that works on the tablet sitting in the kitchen. A stroke survivor doing outpatient rehab needs something the whole family can sign into without a speech-language pathologist unlocking it first. A group home serving adults with developmental disabilities needs accounts for 20 residents, not one. That gap is what I built OpenVoice to fill.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the System Works
&lt;/h2&gt;

&lt;p&gt;OpenVoice is a web-based communication platform that runs in any browser — on phones, tablets, desktop computers, and wall-mounted displays. There is nothing to install and no device requirement. The system includes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Structured Communication Board:&lt;/strong&gt; Six pre-built categories cover the most common communication needs — feelings and emotions, immediate needs, desired actions, people, places, and quick phrases. Every category loads instantly, with color-coded buttons sized for easy tapping even with limited fine motor control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Sentence Builder:&lt;/strong&gt; Users assemble multi-word messages before speaking them. Instead of firing off one word at a time, the sentence builder lets someone construct a complete thought and hear it read aloud in one clean pass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-Person Voice Controls:&lt;/strong&gt; The platform adjusts speaking voice, speech rate, and pitch to match each user's preference and communication environment. A user who needs slower, deliberate speech sets it once and the system remembers it across every device they use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Buttons:&lt;/strong&gt; Caregivers and users add words and phrases specific to their environment. A user's home, classroom, job site, or care setting creates vocabulary that no generic app ships with by default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-User Organization Accounts:&lt;/strong&gt; Schools, clinics, and group homes manage separate communication boards for each person under one account — without mixing settings or profiles between users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overcoming the Friction
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Getting Voice Output to Sound Right on Every Device
&lt;/h3&gt;

&lt;p&gt;The biggest early headache was text-to-speech. Browsers don't all agree on what "default voice" means, and the gap between what we tested on a laptop and what a user heard on a lower-cost Android tablet was significant. On some devices the default voice was a robotic monotone that no user would choose willingly.&lt;/p&gt;

&lt;p&gt;The fix was a persistent voice settings page with a live preview. Every time a user picks up a new device, they can hear a sample before they ever need to communicate in a real moment. The system remembers their voice, rate, and pitch across all their devices. No surprises mid-sentence.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Stopping Bots Before They Got in the Door
&lt;/h3&gt;

&lt;p&gt;The platform launched with a public registration form. Within 48 hours, automated bot registrations outnumbered real users by a wide margin. Because this platform serves a vulnerable population, fake accounts created noise in admin reports and slowed real user onboarding.&lt;/p&gt;

&lt;p&gt;Two layers of invisible protection went in at registration: a hidden trap field that catches automated scripts, and a challenge service that real users never see or interact with but that bots fail automatically. Bot registrations dropped to zero the day those went live.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Business Win
&lt;/h2&gt;

&lt;p&gt;OpenVoice has no meaningful barrier to entry. A family who needs a communication board can have one working in under five minutes — no purchase, no specialty hardware.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Works on What You Already Own:&lt;/strong&gt; Because it runs in the browser, the only hardware requirement is a device with a screen and a speaker. No proprietary tablet, no $8,000 device required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Built for Organizations:&lt;/strong&gt; Schools and group homes with up to 100 users get a single admin panel with isolated per-user boards. One system replaces what would otherwise be dozens of individual app licenses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open to Developers:&lt;/strong&gt; Speech-language pathologists and developers building their own tools can connect to OpenVoice directly, pulling vocabulary data and usage reports into their own systems.&lt;/p&gt;

&lt;p&gt;The next step is expanding the core vocabulary library with clinician-contributed word sets, so new users start with a meaningful communication board instead of building one from scratch.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>a11y</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Built an AI Writing Partner for Service Professionals</title>
      <dc:creator>Scott Steinmetz</dc:creator>
      <pubDate>Wed, 05 Aug 2026 14:00:02 +0000</pubDate>
      <link>https://dev.to/scott_steinmetz/i-built-an-ai-writing-partner-for-service-professionals-2b</link>
      <guid>https://dev.to/scott_steinmetz/i-built-an-ai-writing-partner-for-service-professionals-2b</guid>
      <description>&lt;p&gt;My clients build impressive things for other businesses. But when I ask them to describe their most recent project in plain English, they immediately reach for technical terms their clients would never understand.&lt;/p&gt;

&lt;p&gt;A custom inventory system becomes "a full-stack application with a database backend." A client-facing booking tool becomes "an API-connected web application." The work is real, the results matter — but the words make it sound like homework.&lt;/p&gt;

&lt;p&gt;Portfolio blog posts are how service professionals prove their value to the next client before a sales call ever happens. The challenge is translating the work into language that a business owner actually cares about. No generic AI tool solved this well. They either produced flat, corporate-sounding summaries or repeated the technical details back in slightly different words. What I needed was a writing partner who would ask the right questions first, pull out the human story behind the project, and then write a post that spoke to a decision-maker — not a developer.&lt;/p&gt;

&lt;p&gt;So I built one.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the System Works
&lt;/h2&gt;

&lt;p&gt;The Blog Writing Assistant is a subscription-based AI tool built for service professionals who need to keep their portfolio current without spending hours rewriting technical notes into business language.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Guided Discovery First:&lt;/strong&gt; Before writing a single word, the assistant asks structured questions about the project — who the client is, what problem they were actually trying to solve, where the build got difficult, and what the concrete results looked like. It never asks about the tech stack.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writes for the Right Audience:&lt;/strong&gt; The assistant is built to speak to regional business owners and municipal partners — the exact decision-makers who hire service professionals. It avoids software jargon entirely and translates every technical detail into a plain business result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Conversation, Not a Form:&lt;/strong&gt; Users describe their project naturally, in their own words. The assistant asks follow-up questions, steers toward the most compelling details, and tells you when it has enough to write a strong draft.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured Output Every Time:&lt;/strong&gt; Every post follows the same proven structure — a real-world problem introduction, a plain-English system overview, the honest friction from the build, and the concrete business win. No filler, no generic preamble.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overcoming the Friction
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Keeping the AI On-Voice
&lt;/h3&gt;

&lt;p&gt;The biggest challenge was consistency. A standard AI assistant, given the same project notes, will default to bullet points full of buzzwords and hedged language. The assistant needed a strict ruleset — a list of banned phrases, required structures, and a specific voice — that it would follow every single time without slipping into corporate-speak. Several rounds of testing against real client projects were needed before the output was reliable enough to publish without heavy editing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Protecting the Recipe
&lt;/h3&gt;

&lt;p&gt;The tool is built on a detailed set of writing instructions that took considerable time to develop and refine. A critical requirement was that those instructions never be visible to subscribers. Anyone with enough curiosity can inspect what a website sends and receives behind the scenes. The system had to be structured so the writing instructions stay entirely on the server — subscribers interact with the result, not the ruleset that produces it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Teaching Discovery Before Writing
&lt;/h3&gt;

&lt;p&gt;Early versions jumped to writing too quickly. The draft read like a summary of whatever the user typed first, rather than a real story. The assistant needed to learn to ask before it wrote — to slow down, gather the human details that make a post memorable, and only offer to draft once it had the right raw material. Shifting from "instant output" to "guided conversation then draft" made the final posts significantly stronger and required far less editing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Business Win
&lt;/h2&gt;

&lt;p&gt;The tool produces a complete, publication-ready blog post in a single conversation — typically under twenty minutes. Users arrive with rough project notes and leave with a polished draft written in the voice their clients actually respond to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No Blank Page:&lt;/strong&gt; The biggest reason service professionals do not blog regularly is the time and mental overhead of starting from nothing. The assistant removes both problems by leading the conversation and handling the structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No Rewrite Cycle:&lt;/strong&gt; Because the assistant gathers the story details before writing, the first draft is structurally sound. Subscribers report making minor adjustments to personalize the tone — not wholesale rewrites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistent Portfolio Growth:&lt;/strong&gt; A steady publishing cadence matters for attracting new clients. Removing the blank-page problem means users can close a project and document it the same week, while the details are still fresh.&lt;/p&gt;

&lt;p&gt;The next step is adding industry-specific discovery templates for common project types — municipal technology, retail operations, and commercial construction — so the assistant can ask even more targeted questions from the very first message.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>ChoreQuest: Building a Custom App When Off-the-Shelf Software Fails</title>
      <dc:creator>Scott Steinmetz</dc:creator>
      <pubDate>Sun, 02 Aug 2026 14:00:01 +0000</pubDate>
      <link>https://dev.to/scott_steinmetz/chorequest-building-a-custom-app-when-off-the-shelf-software-fails-1emp</link>
      <guid>https://dev.to/scott_steinmetz/chorequest-building-a-custom-app-when-off-the-shelf-software-fails-1emp</guid>
      <description>&lt;p&gt;My two kids could not complete chores consistently. That's the whole problem.&lt;/p&gt;

&lt;p&gt;We tried several off-the-shelf chore apps. They all share the same design assumption: a recurring chore is a single task that resets when you check it off. Miss Monday? You're blocked. The platform won't generate Tuesday's instance until you either mark Monday done or manually dismiss it.&lt;/p&gt;

&lt;p&gt;For kids, that means one skipped dish-washing session turns into a mountain of overdue items by Thursday, and the whole system collapses under the weight of demotivation.&lt;/p&gt;

&lt;p&gt;What we actually needed was independent chore instances. Monday's dishes and Tuesday's dishes are separate events. Skipping one should not cascade into the next.&lt;/p&gt;

&lt;p&gt;No off-the-shelf app handled that correctly — at least not without locking the workflow or requiring constant parental intervention. So, I built a custom solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the System Works
&lt;/h2&gt;

&lt;p&gt;ChoreQuest is a simple, mobile-friendly household task manager I built to run in the background with zero daily maintenance. The setup includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Works on Everything:&lt;/strong&gt; A single system that runs on our iPhones, Android devices, and a dedicated wall-mounted display in the kitchen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A "Clean Slate" Database:&lt;/strong&gt; The core scheduling engine treats every chore as an isolated event. Completing or skipping Tuesday's chore never touches or messes up Monday's record.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tamper-Proof Tracking:&lt;/strong&gt; The points, streaks, and achievements run entirely on a secure central server. Users cannot artificially inflate their scores or manipulate their task states by messing with the app on their phones.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Our Kitchen Command Center:&lt;/strong&gt; The kitchen wall display uses a simple, secure PIN-code entry, making the system physically accessible to the whole household without needing to hunt down a mobile phone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overcoming the Friction: Making the App Seamless
&lt;/h2&gt;

&lt;p&gt;Building a basic application is easy, but making it friction-free for the end user is where projects succeed or fail. During development, I focused heavily on smoothing out the technical bottlenecks that usually make people abandon custom apps.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Home-Screen Shortcut (Zero-Click Updates)
&lt;/h3&gt;

&lt;p&gt;To make the app as easy to use as possible, I wanted a home-screen widget showing a weekly schedule and a quick-tap checklist.&lt;/p&gt;

&lt;p&gt;Because of how modern phone operating systems isolate background widgets to save battery, the widget couldn't easily verify the user's security log-in. I had to build a custom secure communication path that allows the widget to verify itself independently and cache schedule data locally. The result is a home screen widget that updates instantly without waiting on a slow network connection.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Bulletproof, Silent Updates
&lt;/h3&gt;

&lt;p&gt;Nothing breaks user adoption faster than an app that crashes or displays old data when an update is released.&lt;/p&gt;

&lt;p&gt;I designed the update pipeline so that improvements and bug fixes slide in seamlessly. I programmed the app to automatically detect when a new version is ready, download the update behind the scenes, and restart itself in under two minutes without interrupting whoever is currently looking at the kitchen screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Eliminating "Broken Download" Errors
&lt;/h3&gt;

&lt;p&gt;When testing early versions, downloading an update on Android would occasionally throw a generic "problem parsing the package" error if a user had a stale, partially downloaded file sitting in their phone's local storage folder.&lt;/p&gt;

&lt;p&gt;I resolved this by automating the build pipeline to generate a brand-new, uniquely versioned package for every release. The app now reads the server's version directory directly, ensuring it always pulls down a fresh, uncorrupted file path every single time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Business Win
&lt;/h2&gt;

&lt;p&gt;The metric of success for any utility application is adoption, not features. Both of my kids use ChoreQuest daily without being prompted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Higher Completion Rates:&lt;/strong&gt; The independent-instance model works. When a chore is missed, it sits as a single overdue item rather than cascading into a compounding, demotivating backlog.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Always-On Visibility:&lt;/strong&gt; The kitchen-mounted display ensures the household status is physically visible to everyone at any moment. There are no apps to search for, links to click, or tablets to unlock.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Near-Zero Maintenance:&lt;/strong&gt; The application runs completely unattended. Because the scheduling logic was defined cleanly at launch, the entire platform has required zero administrative adjustments since day one.&lt;/p&gt;

&lt;p&gt;The next step is publishing ChoreQuest directly to the official Apple App Store and Google Play Store, making this zero-friction scheduling model accessible to families outside of a private testing environment.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>productivity</category>
      <category>mobile</category>
    </item>
    <item>
      <title>A One-Click Button to Turn an Order Into a Paid Invoice</title>
      <dc:creator>Scott Steinmetz</dc:creator>
      <pubDate>Thu, 30 Jul 2026 14:00:02 +0000</pubDate>
      <link>https://dev.to/scott_steinmetz/a-one-click-button-to-turn-an-order-into-a-paid-invoice-1636</link>
      <guid>https://dev.to/scott_steinmetz/a-one-click-button-to-turn-an-order-into-a-paid-invoice-1636</guid>
      <description>&lt;p&gt;&lt;em&gt;June 2026&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every small business that bills people runs into the same boring, recurring chore: you do the work, you write up what's owed, you send it off, and then you wait — and sometimes chase. For my print shop, an order isn't a tidy "add to cart and check out" affair. It's a custom job: a quantity here, a setup fee there, shipping, tax, the occasional one-off discount because the customer's a regular. I build each order by hand, and at the end I need to hand the customer a bill they'll actually trust and actually pay.&lt;/p&gt;

&lt;p&gt;I wanted that last step to be a single button. Build the order, click once, and the customer gets an invoice they can pay in seconds. So I built it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why send the bill through PayPal instead of just emailing it myself?
&lt;/h2&gt;

&lt;p&gt;This is the part most people don't expect to be a problem, so let me explain it plainly.&lt;/p&gt;

&lt;p&gt;When a small business sends an email — say, an invoice from &lt;code&gt;myshop.com&lt;/code&gt; — the big mail providers (Gmail, Outlook, and the rest) quietly size it up before deciding whether it lands in the inbox or the spam folder. A little shop sending a money-related email is exactly the kind of thing their filters are nervous about. You can do everything right and &lt;em&gt;still&lt;/em&gt; watch your invoice disappear into a spam folder the customer never checks. Now you're "chasing" a bill the customer literally never saw.&lt;/p&gt;

&lt;p&gt;PayPal doesn't have that problem. When PayPal sends an invoice, it comes from PayPal's own mail system — a sender every inbox on earth already knows and trusts. The customer recognizes it, it lands where it should, and there's a big obvious "Pay Now" button waiting. They can pay with a card or their PayPal balance without creating an account or jumping through hoops.&lt;/p&gt;

&lt;p&gt;So the idea was simple: let &lt;em&gt;me&lt;/em&gt; build the order in my own store, but let &lt;em&gt;PayPal&lt;/em&gt; be the one that delivers the bill and collects the money. Best of both worlds.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the button actually does
&lt;/h2&gt;

&lt;p&gt;Here's the whole experience from my side now:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I build the order in my shop's admin screen, like always.&lt;/li&gt;
&lt;li&gt;I click &lt;strong&gt;Send PayPal Invoice.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The customer gets a real PayPal invoice in their inbox, itemized line by line, and pays it.&lt;/li&gt;
&lt;li&gt;The moment they pay, my store notices on its own and flips the order to &lt;strong&gt;Paid&lt;/strong&gt; — no checking, no manual bookkeeping.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last step is the quietly satisfying one. I don't have to log into PayPal, confirm the payment came through, and then go mark the order paid in my store. The two systems talk to each other and keep themselves in sync. I find out it's paid the same way I find out anything else — the order just says so.&lt;/p&gt;

&lt;p&gt;It sounds simple. Most of the work was in three problems hiding underneath it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem one: the math has to land &lt;em&gt;exactly&lt;/em&gt; on the penny
&lt;/h2&gt;

&lt;p&gt;This one sounds trivial and absolutely is not.&lt;/p&gt;

&lt;p&gt;An order total is the sum of a lot of little pieces: each item's price, multiplied by quantity, plus tax, plus shipping, minus any discount. Computers, like cash registers, have to round somewhere — and when you add up a stack of rounded numbers, the total can drift by a penny or two from what your store says the order is.&lt;/p&gt;

&lt;p&gt;That is not acceptable on an invoice. If my store says the order is $63.50 and PayPal's invoice says $63.51, that one-cent gap is the kind of thing that makes a customer distrust the whole bill — and makes my own books impossible to reconcile at the end of the month.&lt;/p&gt;

&lt;p&gt;So I built the invoice to guarantee, by design, that &lt;strong&gt;the customer pays exactly what the order total says — to the penny, every time.&lt;/strong&gt; It itemizes everything honestly, and then any tiny rounding drift gets reconciled on a single, clearly labeled line so the math always closes perfectly. The customer sees an itemized bill; the total always matches; the books always balance. I tested it with a deliberately awkward order (three items at an odd price, plus shipping, plus a one-cent nudge) and it landed exactly on $63.50. Boring. Exactly the kind of boring I wanted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem two: a bug I could only catch by actually paying
&lt;/h2&gt;

&lt;p&gt;When PayPal tells my store "hey, that invoice just got paid," my store can't just take that message at face value. Anyone on the internet could send a fake "it's paid!" message and try to trick me into shipping an order nobody paid for. So PayPal and my store check each other's identity on every single message, using a kind of tamper-proof wax seal: PayPal seals the message, and my store verifies the seal is intact before believing a word of it.&lt;/p&gt;

&lt;p&gt;Here's the bug. My store, trying to be tidy, was opening the message to read it &lt;em&gt;and then re-folding it&lt;/em&gt; before checking the seal — and the act of re-folding, even though it changed nothing a human could see, broke the seal every time. So every real payment notification got rejected as a possible forgery, and orders never flipped to Paid.&lt;/p&gt;

&lt;p&gt;The maddening part: this bug was &lt;em&gt;invisible&lt;/em&gt; to normal testing. I could throw fake forgeries at it all day and it correctly rejected them — that part worked great. The only way to discover that it was &lt;em&gt;also&lt;/em&gt; rejecting the genuine ones was to run a real payment all the way through with real money and watch the order stubbornly refuse to mark itself paid. The fix was to verify the seal on the original message exactly as it arrived, untouched. Lesson relearned: some bugs only show themselves when you do the real thing end to end, not the rehearsal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem three: the door that was locked the whole time
&lt;/h2&gt;

&lt;p&gt;The last trap cost an afternoon and had the most anticlimactic cause.&lt;/p&gt;

&lt;p&gt;To send invoices on my behalf, my store needs PayPal's permission — a specific permission, "you're allowed to create and send invoices." I'd flipped what looked like the right switch. It saved. It stuck. It &lt;em&gt;looked&lt;/em&gt; granted. And every attempt to send an invoice came back &lt;strong&gt;"not authorized."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It turned out the permission switch I was flipping belonged to the wrong &lt;em&gt;kind&lt;/em&gt; of PayPal account, so flipping it did nothing real — like being handed a key that turns in the lock but doesn't actually move the bolt. Once I set things up on the correct type of business account and turned invoicing on there, the permission took effect immediately and invoices started flowing. No clever fix. Just the right door.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping it safe
&lt;/h2&gt;

&lt;p&gt;Because this plugin handles money and holds the secret keys that let my store act on PayPal's network, I treated security as the starting point, not a finishing touch. The sensitive keys are scrambled where they're stored, so they're useless to anyone who somehow got a look at them. And there's a strict separation between a &lt;strong&gt;practice mode&lt;/strong&gt; (play money, for testing) and &lt;strong&gt;live mode&lt;/strong&gt; (real money) so I could rehearse the entire flow safely before a single real dollar was involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;What looks like one button — &lt;em&gt;Send PayPal Invoice&lt;/em&gt; — is really three quiet guarantees stacked underneath it: the total always matches to the penny, a payment is only believed when it's provably real, and the keys to the money stay locked up. None of that is visible to a customer. It shouldn't be. They get a trustworthy bill in their inbox, pay it in a few clicks, and I find out it's handled without lifting a finger.&lt;/p&gt;

&lt;p&gt;That's the whole goal of a tool like this: take a chore that used to involve logging into two systems, copying numbers between them, and hoping the email didn't land in spam — and turn it into a single click that just works. The interesting engineering is all in service of making the everyday part boring.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Want this for your own store, or need help with a similar setup?&lt;/strong&gt; If you'd like the plugin, or you're wrestling with PayPal invoicing, payment syncing, or a comparable WooCommerce configuration, reach out to me directly at &lt;a href="mailto:scott@steinmetz.ltd"&gt;scott@steinmetz.ltd&lt;/a&gt; — I'm happy to help.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Writing a Linux Driver From Scratch to Watch Free TV on a Raspberry Pi</title>
      <dc:creator>Scott Steinmetz</dc:creator>
      <pubDate>Tue, 28 Jul 2026 03:20:31 +0000</pubDate>
      <link>https://dev.to/scott_steinmetz/writing-a-linux-driver-from-scratch-to-watch-free-tv-on-a-raspberry-pi-40o5</link>
      <guid>https://dev.to/scott_steinmetz/writing-a-linux-driver-from-scratch-to-watch-free-tv-on-a-raspberry-pi-40o5</guid>
      <description>&lt;p&gt;&lt;em&gt;May 2026&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There's a touchscreen mounted in my kitchen — I call it the WallScreen. It runs recipes, the chore board, a calendar, the usual smart-home clutter. One day I decided it should also pull in free over-the-air television. No subscription, no streaming app, just the local broadcast towers that have been beaming HD into the air for free this whole time. I had a Raspberry Pi 5, a $30 USB tuner, and what I assumed would be a boring afternoon.&lt;/p&gt;

&lt;p&gt;It was not a boring afternoon.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tuner that didn't want to work
&lt;/h2&gt;

&lt;p&gt;The tuner I grabbed was a &lt;strong&gt;MyGica A681&lt;/strong&gt; — a tidy little USB TV stick. Plug it into Windows, install the bundled software, done. Plug it into a Raspberry Pi running a current Linux kernel and you get… nothing. The computer notices a device is there and otherwise shrugs.&lt;/p&gt;

&lt;p&gt;Here's why, in two sentences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Linux has no built-in driver for the chips inside this particular stick.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The manufacturer's driver only works on regular PC processors&lt;/strong&gt; — and even then, only as a sealed, prebuilt file with no source code. A Raspberry Pi uses a different kind of chip entirely, so that driver is a non-starter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the whole problem. The hardware is great. It's just that on a Pi, this tuner is a paperweight — and you can't buy or download your way out of it.&lt;/p&gt;

&lt;p&gt;The only way out was to write the driver myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What writing the driver actually involved
&lt;/h2&gt;

&lt;p&gt;A USB TV tuner isn't one chip — it's a little team of them working together. One chip is the "translator" that lets the computer talk to the device over USB. Another tunes to a channel, like turning a radio dial. A third converts the broadcast signal into video data the computer can use.&lt;/p&gt;

&lt;p&gt;The good news: for the parts that handle tuning and decoding the signal, I was able to build on existing open-source work from the broader Linux TV community — code other people had already written and shared for the chips inside this stick. (It's all credited in the project.)&lt;/p&gt;

&lt;p&gt;The missing piece — the part nobody had written — was the &lt;strong&gt;translator layer&lt;/strong&gt;: the code that tells Linux "this device exists, here's how to send it commands, and here's how to pull the live TV stream out of it." That's the driver I built from scratch. Once it was in place, the existing pieces could finally do their jobs, and the signal had a path from the antenna all the way to the screen.&lt;/p&gt;

&lt;p&gt;In theory.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug that ate the afternoon
&lt;/h2&gt;

&lt;p&gt;When I first loaded everything up, the tuner reported that it had &lt;em&gt;locked onto a real TV station.&lt;/em&gt; Every indicator was green. And it produced &lt;strong&gt;zero video.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A tuner that's "locked on" but sends no picture is a uniquely maddening problem, because nothing looks broken. I spent hours convinced I had a setting backwards, and tried every variation I could think of to coax data out of it.&lt;/p&gt;

&lt;p&gt;The fix, embarrassingly, was to &lt;strong&gt;change nothing.&lt;/strong&gt; The code I'd built on came with a sensible default for how the video data should flow out of the device — and that default was correct all along. The moment I'd "helpfully" switched it to what I assumed was the right mode, I'd broken it. I put the default back and the live TV stream came pouring out.&lt;/p&gt;

&lt;p&gt;The lesson I keep relearning in this kind of work: when something already ships with a sensible default, the burden of proof is on &lt;em&gt;changing&lt;/em&gt; it — not on second-guessing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  When the instruments lie
&lt;/h2&gt;

&lt;p&gt;The second trap was sneakier. With video finally flowing, I checked the tuner's own readouts for signal quality — strength, error rate, that sort of thing. They were &lt;strong&gt;terrible&lt;/strong&gt;: numbers that said the signal was practically nonexistent, on a channel that was playing flawlessly right in front of me.&lt;/p&gt;

&lt;p&gt;It turned out those particular readouts were never actually implemented for this chip — they just report meaningless noise. If I'd trusted them, I'd have concluded my working driver was broken and thrown it away.&lt;/p&gt;

&lt;p&gt;So I stopped trusting the dashboard and started checking the data directly: a tiny script that grabs a few seconds of the live stream and confirms it has the structure a real TV broadcast should have. If it does, the driver works — full stop, no matter what the instruments claim. That capture-and-check became my real source of truth, and it's the method I recommend to anyone using the driver.&lt;/p&gt;

&lt;p&gt;The payoff: it locked cleanly onto my local stations and pulled in every channel and subchannel they broadcast.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it last
&lt;/h2&gt;

&lt;p&gt;A driver that works today but breaks the next time the Pi updates itself is just a future headache. So I packaged it to &lt;strong&gt;rebuild itself automatically&lt;/strong&gt; whenever the system installs a new version of Linux, and to load the moment the tuner is plugged in. Install it once and forget it's there.&lt;/p&gt;

&lt;h2&gt;
  
  
  From "it works" to "TV anywhere in the house"
&lt;/h2&gt;

&lt;p&gt;A working driver gives you raw data, not a TV experience. To finish the job I layered the standard open-source TV software on top: a backend that scans the airwaves and organizes everything into proper channels, and a TV-style interface on the WallScreen itself with a one-tap launcher.&lt;/p&gt;

&lt;p&gt;The fun part is how many ways the rest of the house can now watch the same antenna:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Straight from a web browser.&lt;/strong&gt; Any device on my home Wi-Fi can open a page and start watching — no app to install. To keep this smooth, the actual video conversion is offloaded to my ProDesk, a more powerful machine on the network, so the little Pi isn't stuck doing the heavy lifting just to feed a browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Through a free TV app.&lt;/strong&gt; On a phone, laptop, or another TV box, you can install Kodi (a free, open-source media app), point it at the home TV server's address, and get the full channel guide and a proper remote-friendly interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's one honest limitation to call out: I'm using a &lt;strong&gt;single tuner.&lt;/strong&gt; A tuner can only sit on one channel at a time — but it can hand that one channel out to as many screens as I want. So the whole house can watch the same station together with no trouble; what it &lt;em&gt;can't&lt;/em&gt; do is let one person watch the news while someone else watches a game on a different channel. That would take a &lt;strong&gt;multi-tuner device&lt;/strong&gt; (something like a multi-tuner network TV box that holds several channels at once). For now, one tuner covers how we actually watch, and stepping up is just a matter of swapping in bigger hardware later — the software already handles it.&lt;/p&gt;

&lt;p&gt;A couple of other things this setup &lt;em&gt;can&lt;/em&gt; do that I deliberately left for a future upgrade, to keep the first version simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Watching from outside the house&lt;/strong&gt; — secure remote access so I could pull up local channels while traveling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recording shows (DVR)&lt;/strong&gt; — the software supports scheduling recordings like a TiVo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are well within reach with what's already running; I just chose to get live TV rock-solid first and treat those as phase two.&lt;/p&gt;

&lt;p&gt;There was also one last gremlin worth a mention: the TV software kept crashing and restarting mid-show, which &lt;em&gt;looked&lt;/em&gt; like a flaky signal but turned out to be a single bad default value buried in its streaming settings. One corrected setting and it's been rock-solid since.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;What started as "let me plug in a TV tuner" turned into reverse-engineering how the device talks, writing a piece of the operating system by hand, and chasing down two bugs that each disguised themselves as something they weren't. That's the nature of this kind of work: the hardware is rarely the hard part — it's the undocumented gaps between the pieces.&lt;/p&gt;

&lt;p&gt;The kitchen screen now plays free local HD on tap — and so does every phone, laptop, and TV in the house. The best part: the next person who buys this same tuner for their Raspberry Pi doesn't have to spend the afternoon I spent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I've published the complete, working driver on GitHub so anyone can use it:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/LordLuktor/mygica-a681-linux-driver" rel="noopener noreferrer"&gt;https://github.com/LordLuktor/mygica-a681-linux-driver&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clone it, run the installer, plug in your tuner, and you're watching TV — no proprietary software, no subscription, no fuss. It's free and open-source, with full credit to the open-source TV community whose work made it possible.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>linux</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
