<?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: Alexandru A</title>
    <description>The latest articles on DEV Community by Alexandru A (@programmer4web).</description>
    <link>https://dev.to/programmer4web</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%2F3862880%2Febd2d0a8-5feb-4c94-a413-17e5769bd609.png</url>
      <title>DEV Community: Alexandru A</title>
      <link>https://dev.to/programmer4web</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/programmer4web"/>
    <language>en</language>
    <item>
      <title>How I Used AI Tools to Create a SaaS Demo Video as a Solo Developer</title>
      <dc:creator>Alexandru A</dc:creator>
      <pubDate>Thu, 02 Jul 2026 16:11:21 +0000</pubDate>
      <link>https://dev.to/programmer4web/how-i-used-ai-tools-to-create-a-saas-demo-video-as-a-solo-developer-3145</link>
      <guid>https://dev.to/programmer4web/how-i-used-ai-tools-to-create-a-saas-demo-video-as-a-solo-developer-3145</guid>
      <description>&lt;p&gt;Creating a product demo video for a SaaS launch sounds straightforward until you actually sit down to do it. As a solo developer launching Evaficy Smart Test on Product Hunt, I had no active video production setup, no marketing team, and no budget for professional editing. I did have some basic video editing knowledge from about ten years ago, enough to understand tracks, timelines, and how to import files — but nothing recent and nothing close to professional production experience. Here is how AI-assisted tools bridged that gap and made the entire process not just possible but genuinely good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting with AI consultation
&lt;/h2&gt;

&lt;p&gt;The first step was not picking up a camera or opening an editor. It was thinking through the structure. I consulted with Claude to build a script optimized specifically for a Product Hunt audience — short attention spans, technical viewers, and a 60 to 90 second sweet spot for demo videos. The script went through several iterations: adjusting the opening to lead with value rather than complaints about the problem space, trimming feature coverage to the three or four most impactful moments, and rewriting every sentence for &lt;strong&gt;AI voiceover&lt;/strong&gt; pacing — shorter sentences, no ambiguous numbers, natural pause points between scenes.&lt;br&gt;
The consultation also produced something I would not have thought of independently: splitting the recording into separate scene clips rather than one continuous screen recording. The reasoning was simple — if one scene needs a retake, you redo 15 seconds, not the entire video. This single decision saved significant time during editing.&lt;/p&gt;
&lt;h2&gt;
  
  
  Choosing the right tools for each job
&lt;/h2&gt;

&lt;p&gt;A trap many developers fall into is reaching for the most powerful tool available rather than the most appropriate one. For &lt;strong&gt;screen recording&lt;/strong&gt;, Windows Snipping Tool was genuinely sufficient. It captures at 1080p, exports clean MP4 files, and requires zero setup. No OBS configuration, no scene management, no learning curve. For a silent screen capture of a web application UI, it was exactly the right tool.&lt;br&gt;
For AI voiceover I used ElevenLabs Text to Speech — the only part of this entire production where I spent any money, approximately 7 USD for the full script across all six scenes. The settings that produced natural calm narration suitable for a technical SaaS product:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Voice: Joseff Novak — Calm and Professional&lt;/li&gt;
&lt;li&gt;Model: Eleven Multilingual v2&lt;/li&gt;
&lt;li&gt;Speed: 0.98&lt;/li&gt;
&lt;li&gt;Stability: 60%&lt;/li&gt;
&lt;li&gt;Similarity Boost: 75%&lt;/li&gt;
&lt;li&gt;Style: 0%&lt;/li&gt;
&lt;li&gt;Speaker Boost: Enabled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The stability at 60% gave consistent delivery without sounding robotic, while the slightly reduced speed at 0.98 added natural breathing room between sentences. Generating each scene as a separate audio clip rather than one long file made timeline alignment in the editor significantly easier.&lt;/p&gt;

&lt;p&gt;For editing I used &lt;strong&gt;DaVinci Resolve&lt;/strong&gt; free version — no watermark, no length limit, full 1080p export at 30fps as H.264 MP4. My ten year old video editing knowledge was just enough to feel oriented in the interface: I understood what tracks were, how importing worked, and the general concept of a timeline. What I did not know — specifically how to add separate audio tracks and unlink video from its embedded silent audio — took about fifteen minutes of trial and error to figure out. The free version handled everything needed for a straightforward assembly edit without any paid features. The YouTube preset in the Deliver tab handled all the technical export settings automatically.&lt;/p&gt;

&lt;p&gt;For hosting, YouTube was the natural choice — free, reliable, and dev.to renders YouTube links as embedded players automatically when you paste the URL on its own line.&lt;/p&gt;
&lt;h2&gt;
  
  
  The scene-by-scene approach in practice
&lt;/h2&gt;

&lt;p&gt;The final video runs approximately 82 seconds across six scenes, each recorded separately against the actual product UI at app.evaficy.com:&lt;/p&gt;

&lt;p&gt;Homepage hero section overview (8 seconds)&lt;br&gt;
Projects and Scenarios view (12 seconds)&lt;br&gt;
AI test case generation in action (15 seconds)&lt;br&gt;
Test runs overview with step by step execution, pass/fail tracking, and the defect creation form (22 seconds — the most complex scene, intentionally given more time)&lt;br&gt;
AI Risk Insights dashboard (13 seconds)&lt;br&gt;
Sign-up and CTA screen (12 seconds)&lt;/p&gt;

&lt;p&gt;The 22 second test runs scene is worth noting specifically. The initial script allocated 15 seconds but the feature complexity genuinely required more time to demonstrate meaningfully. Rather than rushing it, I extended that scene and adjusted the voiceover script accordingly. Having separate clips made this a simple timeline adjustment rather than a full re-record.&lt;/p&gt;

&lt;p&gt;The result&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/NQBM6-UYqjc"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What AI actually changed
&lt;/h2&gt;

&lt;p&gt;The honest conclusion is not that AI replaced skill or effort — it is that AI compressed the learning curve and filled the gaps where inexperience or rustiness would have otherwise created a bottleneck. Script structure that would have taken hours of research came from a conversation. Voiceover that would have required hiring a narrator or recording myself as a non-native English speaker came from a text input and approximately 7 USD in ElevenLabs credits. Remembering how DaVinci Resolve's track system worked took minutes of guided trial and error rather than watching hours of tutorials.&lt;br&gt;
The creative and technical decisions were still mine. AI handled the parts where a ten year gap in experience would have slowed everything down.&lt;br&gt;
For &lt;strong&gt;solo developers&lt;/strong&gt; building in public with no marketing budget, that compression matters. The total production cost was under 7 USD. The tools are good enough now that production quality is no longer gated behind budget, specialization, or an unbroken decade of keeping your skills current.&lt;/p&gt;

&lt;p&gt;Have you created a demo video for your own product? What tools did you use and what would you do differently? Drop it in the comments.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Evaficy Smart Test is live on Product Hunt today if you are curious what I have been building&lt;/em&gt;:&lt;br&gt;
&lt;a href="https://www.producthunt.com/products/evaficy-smart-test?utm_source=other&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Evaficy Smart Test on Product Hunt&lt;/a&gt;&lt;br&gt;
&lt;a href="https://app.evaficy.com" rel="noopener noreferrer"&gt;Evaficy Smart Test&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>tutorial</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Chasing a Ghost: Debugging a Silent Google OAuth Failure in Production</title>
      <dc:creator>Alexandru A</dc:creator>
      <pubDate>Thu, 02 Jul 2026 09:22:33 +0000</pubDate>
      <link>https://dev.to/programmer4web/chasing-a-ghost-debugging-a-silent-google-oauth-failure-in-production-p4j</link>
      <guid>https://dev.to/programmer4web/chasing-a-ghost-debugging-a-silent-google-oauth-failure-in-production-p4j</guid>
      <description>&lt;p&gt;Yesterday I launched &lt;a href="https://www.producthunt.com/products/evaficy-smart-test?utm_source=other&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Evaficy Smart Test&lt;/a&gt; on Product Hunt — an AI-powered QA platform I've been building solo. Quiet launch, but that's not really what this post is about.&lt;/p&gt;

&lt;p&gt;This morning I woke up to intermittent &lt;code&gt;invalid_grant&lt;/code&gt; errors on Google Sign-In in production. No clear pattern. No reliable way to reproduce it by clicking around myself. Just the occasional 500, logged with no obvious trigger next to it.&lt;/p&gt;

&lt;p&gt;Here's how I tracked it down — because the actual cause turned out to be something I wouldn't have guessed, and I suspect it's more common than people realize.&lt;/p&gt;

&lt;h2&gt;
  
  
  The symptom
&lt;/h2&gt;

&lt;p&gt;Users occasionally hit a 500 error trying to sign in with Google. Not every time. Not for every user. No visible pattern in &lt;em&gt;when&lt;/em&gt; it happened.&lt;/p&gt;

&lt;p&gt;The stack trace pointed at &lt;code&gt;passport-oauth2&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TokenError: Bad Request
    at OAuth2Strategy.parseErrorResponse
    at OAuth2Strategy._createOAuthError
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Classic &lt;code&gt;invalid_grant&lt;/code&gt; — Google rejecting an authorization code as invalid, expired, or already used.&lt;/p&gt;

&lt;h2&gt;
  
  
  The obvious suspects (all wrong)
&lt;/h2&gt;

&lt;p&gt;My first instinct was &lt;strong&gt;double-invocation&lt;/strong&gt; — somewhere, the same authorization code was probably being sent to Google twice. Common causes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A router mounted twice (I actually found a comment in my own code from a past bug: &lt;code&gt;// Bug fixed: was '/auth/google' (double prefix since router is mounted at /auth)&lt;/code&gt; — promising lead, right?)&lt;/li&gt;
&lt;li&gt;A React &lt;code&gt;useEffect&lt;/code&gt; firing twice, maybe due to StrictMode&lt;/li&gt;
&lt;li&gt;The OAuth callback route being hit twice in the middleware chain
I checked all three. All clean. The router was mounted exactly once. The frontend button did a plain &lt;code&gt;window.location.href&lt;/code&gt; redirect — no React state, no effects anywhere near the callback. The middleware chain had no loop-back.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dead ends, but useful ones — they narrowed the search.&lt;/p&gt;

&lt;h2&gt;
  
  
  The clue that mattered
&lt;/h2&gt;

&lt;p&gt;I asked for the actual server logs instead of trying to reproduce the bug live (reproducing intermittent bugs by clicking around is a great way to burn an afternoon for nothing). One log entry stood out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/auth/google/callback?iss=https%3A%2F%2Faccounts.google.com&amp;amp;code=...
&amp;amp;scope=email+profile+...&amp;amp;authuser=2&amp;amp;prompt=none"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;prompt=none&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;My actual "Continue with Google" button used &lt;code&gt;prompt: 'select_account'&lt;/code&gt; — it always produces an interactive flow with a visible account picker. It would &lt;em&gt;never&lt;/em&gt; generate a &lt;code&gt;prompt=none&lt;/code&gt; callback. That single query parameter meant this request wasn't coming from a real click on my button at all. Something else was silently triggering Google auth in the background.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual cause
&lt;/h2&gt;

&lt;p&gt;A quick grep through the frontend turned up this, still mounted at the app root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GoogleOAuthProvider&lt;/span&gt; &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Authentication&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;GoogleOAuthProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;GoogleOAuthProvider&lt;/code&gt; is from &lt;code&gt;@react-oauth/google&lt;/code&gt; — a &lt;em&gt;different&lt;/em&gt;, client-side OAuth pattern than the one I was actually using. My real login flow was 100% server-side: browser redirect → Express → &lt;code&gt;passport-google-oauth20&lt;/code&gt; → session. Textbook, and it worked fine on its own.&lt;/p&gt;

&lt;p&gt;But at some earlier point I'd started migrating toward the client-side flow, wired up the provider, wrote a &lt;code&gt;useGoogleLogin&lt;/code&gt; hook — then abandoned it and commented the hook out. The provider, though, stayed mounted.&lt;/p&gt;

&lt;p&gt;Here's the part that got me: &lt;strong&gt;commenting out the hook doesn't stop the provider from doing anything.&lt;/strong&gt; &lt;code&gt;GoogleOAuthProvider&lt;/code&gt; loads Google's Identity Services script the moment it renders, regardless of whether anything downstream actually consumes its context. That script can independently trigger a silent/background re-authentication check using the same &lt;code&gt;client_id&lt;/code&gt; — completely decoupled from any button click. Since that client ID's redirect URI pointed at my real callback endpoint, the silent flow's (possibly stale or already-consumed) code was landing on my production auth route and getting rejected by Google as &lt;code&gt;invalid_grant&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dead code, alive side effects. The import was unused. The component it wrapped didn't need it. But the script it loaded was doing something the whole time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix&lt;/strong&gt; was one line of removal — dropping the provider wrapper entirely, since nothing in the active code path used it. I also hardened the callback handler itself, since &lt;code&gt;TokenError&lt;/code&gt; was throwing &lt;em&gt;before&lt;/em&gt; passport's &lt;code&gt;failureRedirect&lt;/code&gt; logic could catch it, turning a normal auth failure into an unhandled 500:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/google/callback&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;passport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;google&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;clientUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?auth_error=google`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logIn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginErr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginErr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loginErr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;})(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* existing session logic */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dead code isn't always inert.&lt;/strong&gt; An unused import can still execute side effects the moment it's rendered/loaded — check what a component &lt;em&gt;does on mount&lt;/em&gt;, not just whether anything reads its output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A single unexplained query parameter can be the whole story.&lt;/strong&gt; &lt;code&gt;prompt=none&lt;/code&gt; was the one detail that ruled out every "obvious" theory and pointed straight at the real cause.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs before reproduction, when the bug is intermittent.&lt;/strong&gt; I never had to manually trigger this bug once — the production logs had already recorded exactly the parameter I needed to diagnose it.
If you're running Google OAuth alongside any client-side Google library (&lt;code&gt;@react-oauth/google&lt;/code&gt;, &lt;code&gt;google-one-tap&lt;/code&gt;, etc.) — even ones you think are unused — it's worth checking whether they're still mounted somewhere, quietly doing their own thing in the background.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Building &lt;a href="https://www.producthunt.com/products/evaficy-smart-test?utm_source=other&amp;amp;utm_medium=social" rel="noopener noreferrer"&gt;Evaficy Smart Test&lt;/a&gt;, an AI-powered QA/test case generation platform, solo. Happy to answer questions about the debugging process or the product itself in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>oauth</category>
      <category>mongodb</category>
      <category>node</category>
    </item>
    <item>
      <title>I built an AI-powered QA platform because manual testing tools haven't kept up — launching on Product Hunt today</title>
      <dc:creator>Alexandru A</dc:creator>
      <pubDate>Wed, 01 Jul 2026 00:54:59 +0000</pubDate>
      <link>https://dev.to/programmer4web/i-built-an-ai-powered-qa-platform-because-manual-testing-tools-havent-kept-up-launching-on-3h64</link>
      <guid>https://dev.to/programmer4web/i-built-an-ai-powered-qa-platform-because-manual-testing-tools-havent-kept-up-launching-on-3h64</guid>
      <description>&lt;p&gt;For the past year and a half, I've been building &lt;strong&gt;Evaficy Smart Test&lt;/strong&gt; — a QA platform for manual testing teams that brings AI into the parts of the workflow that are still painfully manual: writing test cases, tracking validation, and figuring out what to test before a release.&lt;/p&gt;

&lt;p&gt;We're launching on Product Hunt today, and I wanted to share the story behind it, plus some of the technical decisions along the way.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/NQBM6-UYqjc"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The problem&lt;br&gt;
Most QA tooling falls into two buckets: traditional test management tools (think spreadsheets with extra steps), or newer AI tools that focus almost entirely on test automation — generating Selenium/Playwright scripts, self-healing locators, that kind of thing.&lt;br&gt;
But a huge number of QA teams are still doing manual testing — and that segment hasn't gotten much attention from AI tooling. Writing comprehensive test cases, covering edge cases, tracking validation across reviewers, linking failed tests to defects — all of that is still mostly manual, repetitive work.&lt;/p&gt;

&lt;p&gt;What I built&lt;br&gt;
Evaficy Smart Test covers the full manual QA workflow:&lt;/p&gt;

&lt;p&gt;Projects &amp;amp; Scenarios — organize test cases by project, with role-based access for Owners, POs, Tech Leads, and QA&lt;br&gt;
AI test case generation — generate comprehensive test cases (including edge cases and negative scenarios) based on test type and affected page&lt;br&gt;
Expert validation — PO/Tech Lead review workflow before test cases go live&lt;br&gt;
Test runs — step-by-step execution with real-time pass/fail tracking&lt;br&gt;
Defect tracking — inline defect logging with full traceability, one-click push to Jira&lt;br&gt;
AI Risk Insights — scores scenarios by failure risk using historical test run data, so teams know where to focus before a release&lt;/p&gt;

&lt;p&gt;Stack &amp;amp; technical notes&lt;br&gt;
Built with React and Material UI on the frontend, with Stripe for subscription billing. Some of the more interesting build challenges:&lt;/p&gt;

&lt;p&gt;Designing the AI generation flow to feel fast and controllable rather than a black box — letting users specify criteria (test type, affected page, custom fields) rather than just a free-text prompt&lt;br&gt;
Building the validation workflow so AI-generated and manually-written test cases go through the same review process, since trust in test cases matters more than where they came from&lt;br&gt;
Keeping the defect → Jira sync simple (one click, no field mapping headaches) since context-switching is the #1 complaint QA teams have about their current tools&lt;/p&gt;

&lt;p&gt;Try it out&lt;br&gt;
If you work in QA, or you're a dev/PM who's tired of testing falling through the cracks, I'd genuinely love your feedback.&lt;br&gt;
🚀 We're live on Product Hunt today: &lt;a href="https://www.producthunt.com/products/evaficy-smart-test?launch=evaficy-smart-test" rel="noopener noreferrer"&gt;Evaficy Smart Test - Launch Page&lt;/a&gt;&lt;br&gt;
🔗 Try Evaficy Smart Test: &lt;a href="https://app.evaficy.com" rel="noopener noreferrer"&gt;Evaficy Smart Test&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer any questions about the build, the AI integration, or manual QA workflows in general — drop a comment below!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>saas</category>
      <category>qa</category>
    </item>
    <item>
      <title>AI Made Me a Better Reviewer (The Hard Way)</title>
      <dc:creator>Alexandru A</dc:creator>
      <pubDate>Mon, 13 Apr 2026 03:45:53 +0000</pubDate>
      <link>https://dev.to/programmer4web/ai-made-me-a-better-reviewer-the-hard-way-3dm5</link>
      <guid>https://dev.to/programmer4web/ai-made-me-a-better-reviewer-the-hard-way-3dm5</guid>
      <description>&lt;p&gt;I build a SaaS QA platform. When AI coding assistants became good enough to trust with real work, I leaned in — and my velocity went up noticeably. Less boilerplate, faster feature implementation, fewer rabbit holes on syntax I'd forgotten.&lt;/p&gt;

&lt;p&gt;But something shifted that I didn't expect. I wasn't writing less code and saving time. I was writing less code and reviewing more instead.&lt;/p&gt;

&lt;p&gt;For a while I thought that was fine. Then one evening I pushed a feature involving Google SSO and suddenly users couldn't log in. Not "the Google button doesn't work" — I mean the entire sign-in and logout flow was broken. Silent. No obvious error.&lt;/p&gt;

&lt;p&gt;I dug in. The AI had been working on routing middleware to serve pre-rendered pages for SEO. Reasonable task. What it also did, without flagging it, was intercept every GET request that looked like a browser navigation — including /auth/google. The OAuth redirect came back from Google, hit the middleware, got served the SPA shell instead, and the session was never established.&lt;/p&gt;

&lt;p&gt;The fix was one line. The damage could have been significant if it had reached more users.&lt;/p&gt;

&lt;p&gt;Here's what stayed with me: the feature it was building worked perfectly. The tests I ran against the new functionality passed. What broke was something adjacent — code I didn't ask it to touch, changed in a way that was internally logical but contextually wrong.&lt;/p&gt;

&lt;p&gt;That's the real lesson about working with AI on production code. It doesn't lack skill. It lacks awareness of consequences outside the task boundary. It will solve the problem you gave it and not think twice about what it quietly rearranged to get there.&lt;/p&gt;

&lt;p&gt;So now I review differently. I don't just check that the feature works. I read the diff the way I'd read a pull request from a smart junior developer who might not know what they don't know — looking for what changed that I didn't ask to change.&lt;/p&gt;

&lt;p&gt;The trade-off is real: I write far less code than before, but I spend more time in review. Whether that's a net win depends on how careful you are. If you test properly and treat every AI output as a PR that needs approval, the productivity gain holds. If you trust the result because the happy path works, you're accumulating invisible risk.&lt;/p&gt;

&lt;p&gt;I've caught CORS middleware generating 500 stack traces from bot traffic. A VAT field being HTML-encoded into / before storing in the database. A soft-delete flag silently stripped from a user object because the context mapper didn't know about the new field.&lt;/p&gt;

&lt;p&gt;Each one was a sensible decision in isolation. Each one was wrong in context.&lt;/p&gt;

&lt;p&gt;AI didn't make me a worse engineer. But it did make me a much more deliberate reviewer. That wasn't in the marketing material.&lt;/p&gt;

&lt;p&gt;Do you have similar situations — where AI solved the task but broke something it wasn't supposed to touch? How do you review AI-generated code differently now?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>codereview</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How Do You Actually Integrate Jira and CI/CD Into a Real Web Application?</title>
      <dc:creator>Alexandru A</dc:creator>
      <pubDate>Sat, 11 Apr 2026 11:31:24 +0000</pubDate>
      <link>https://dev.to/programmer4web/how-do-you-actually-integrate-jira-and-cicd-into-a-real-web-application-417d</link>
      <guid>https://dev.to/programmer4web/how-do-you-actually-integrate-jira-and-cicd-into-a-real-web-application-417d</guid>
      <description>&lt;p&gt;When you first hear about integrating Jira with CI/CD, it often sounds abstract—like something happening “around” your application rather than inside it. But once you start building a real system, you quickly realize the challenge is very concrete:&lt;/p&gt;

&lt;p&gt;How do you connect your &lt;strong&gt;codebase, pipelines, and issue tracking&lt;/strong&gt; into one coherent flow?&lt;/p&gt;

&lt;p&gt;Recently, while working on a quality assurance platform, I had to implement this integration from scratch—and the biggest lesson was this: integration is not a feature, it’s an architecture decision.&lt;/p&gt;

&lt;p&gt;At the application level, everything starts with traceability. Your web app doesn’t directly “talk” to Jira in most cases, but your development workflow does. The first real bridge between your application and Jira is your version control strategy. By enforcing that every branch and commit references a Jira ticket, you create a consistent link between code and requirement. This small discipline allows Jira to automatically reflect development activity without any custom logic inside your application.&lt;/p&gt;

&lt;p&gt;From there, CI/CD becomes the execution engine. Tools like Jenkins or GitHub Actions take over whenever code is pushed. They build your application, run validations, and determine whether the current state of the code is reliable. At this point, your application is indirectly part of the integration: every change to it triggers a pipeline that evaluates its health.&lt;/p&gt;

&lt;p&gt;The real integration happens when you close the loop between pipelines and Jira. A CI/CD system that only runs builds is useful, but not enough. The moment it starts sending results back—marking tickets as ready, blocked, or completed—you move from automation to coordination. This is where your application lifecycle becomes visible to the entire team.&lt;/p&gt;

&lt;p&gt;In practice, this often means configuring your pipeline to communicate with Jira through existing integrations or APIs. For example, after a successful build, a ticket can automatically move to a “Ready for Testing” state. If something fails, the same ticket can be flagged or annotated with the failure context. None of this requires your web application to change—but it fundamentally changes how your application is delivered and validated.&lt;/p&gt;

&lt;p&gt;While implementing this for a QA-focused platform, I went a step further and introduced a few key capabilities to make the integration truly practical in real-world scenarios. One of them was &lt;strong&gt;personal access tokens&lt;/strong&gt;, allowing users to securely authenticate API requests and integrate the platform with CI/CD pipelines, scripts, and internal tools—without exposing credentials. This made automation much safer and easier to adopt.&lt;/p&gt;

&lt;p&gt;Another important piece was the ability to &lt;strong&gt;push defects directly to Jira&lt;/strong&gt;, including detailed information and reproduction steps. Instead of manually copying bugs, test failures could be turned into structured Jira issues instantly, improving both speed and consistency in defect tracking.&lt;/p&gt;

&lt;p&gt;Finally, I implemented &lt;strong&gt;CI/CD-triggered Test Runs&lt;/strong&gt;, where pipelines can automatically create test runs as part of the delivery process. This ensures that every build is not just compiled, but also prepared for structured and traceable manual testing, fully connected back to Jira.&lt;/p&gt;

&lt;p&gt;One subtle but important realization is that your application’s structure influences how effective this integration can be. If your project lacks clear environments, consistent build steps, or reliable test execution, even the best Jira integration will feel unreliable. In other words, CI/CD doesn’t fix chaos—it exposes it.&lt;/p&gt;

&lt;p&gt;What truly defines a good integration is not how many tools you connect, but how well they communicate. A well-integrated setup creates a powerful effect: your Jira board becomes a real-time reflection of your application’s state. You no longer rely on manual updates or status meetings, because the system itself tells the story.&lt;/p&gt;

&lt;p&gt;In the end, integrating Jira and CI/CD into a web application is not about embedding APIs into your frontend or backend. It’s about connecting the lifecycle around your application so tightly that every change is tracked, validated, and visible.&lt;/p&gt;

&lt;p&gt;And once that happens, your application is no longer just code—it becomes part of a system that continuously proves its own quality.&lt;/p&gt;

&lt;p&gt;So the real question is not whether you can integrate Jira and CI/CD…&lt;/p&gt;

&lt;p&gt;…but whether your application lifecycle is structured well enough to support it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>automation</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What happens when you give an AI your acceptance criteria and ask it to write test cases?</title>
      <dc:creator>Alexandru A</dc:creator>
      <pubDate>Mon, 06 Apr 2026 06:13:08 +0000</pubDate>
      <link>https://dev.to/programmer4web/what-happens-when-you-give-an-ai-your-acceptance-criteria-and-ask-it-to-write-test-cases-1d3</link>
      <guid>https://dev.to/programmer4web/what-happens-when-you-give-an-ai-your-acceptance-criteria-and-ask-it-to-write-test-cases-1d3</guid>
      <description>&lt;p&gt;After years of building frontend applications across e-health and e-learning products, I've sat in enough sprint reviews to notice a pattern: &lt;em&gt;QA test cases&lt;/em&gt; are written the same way every time. Happy path first, a handful of negative cases if the deadline allows, edge cases if the tester has seen that bug before.&lt;/p&gt;

&lt;p&gt;The process is repetitive, experience-dependent, and the first thing to get cut when a release is running late.&lt;/p&gt;

&lt;p&gt;So I started experimenting — feeding acceptance criteria directly to an AI and asking for a complete test suite. Here's an honest account of what works, what doesn't, and what it actually changes about the process.&lt;/p&gt;

&lt;p&gt;What the AI gets right immediately&lt;/p&gt;

&lt;p&gt;The output quality on structured coverage is genuinely impressive. Given clear acceptance criteria, the AI will produce happy path cases, negative scenarios, boundary conditions, and precondition states faster than any manual process — and it won't skip the boring ones.&lt;/p&gt;

&lt;p&gt;It also structures the output consistently: steps, expected results, preconditions. That consistency alone has value when you're maintaining a growing test library across releases.&lt;/p&gt;

&lt;p&gt;Where it falls short&lt;/p&gt;

&lt;p&gt;The AI has no knowledge of your system beyond what you give it. It doesn't know that your application handles an unauthenticated empty cart differently from an authenticated one, or that a particular field has a known edge case from three sprints ago.&lt;/p&gt;

&lt;p&gt;More critically: vague acceptance criteria produce vague test cases. With a human tester, ambiguity triggers a question. With an AI, it triggers a confident but incorrect assumption. If your requirements only describe the happy path, the generated test suite will skew heavily toward the happy path.&lt;/p&gt;

&lt;p&gt;What actually determines the output quality&lt;/p&gt;

&lt;p&gt;After enough iterations, the pattern is consistent: the quality of the generated tests is almost entirely determined by the quality of the input. A few things that made a measurable difference:&lt;/p&gt;

&lt;p&gt;Write constraints explicitly. "The form should validate correctly" is not a requirement. "The email field must reject inputs without an @ symbol and a valid domain" is.&lt;br&gt;
Include failure conditions in your acceptance criteria. If you only document what should succeed, the AI will generate tests for success.&lt;br&gt;
Specify the user role and context. "As an admin" and "as a guest" produce meaningfully different test suites for the same feature.&lt;br&gt;
Add environment context. First-time user vs returning user, mobile vs desktop, authenticated vs unauthenticated — these details shape coverage significantly.&lt;br&gt;
An honest assessment&lt;/p&gt;

&lt;p&gt;AI doesn't replace a QA engineer. It replaces the first draft.&lt;/p&gt;

&lt;p&gt;A good tester still needs to review the output, discard cases that don't apply to the actual system, and add scenarios based on knowledge no requirements document captures. That judgment isn't going away.&lt;/p&gt;

&lt;p&gt;But the shift from writing to reviewing is more significant than it sounds. Starting with 80% of the test suite already structured means your QA effort goes toward the cases that actually require expertise — the ones that come from understanding the system, not from reading the spec.&lt;/p&gt;

&lt;p&gt;That's a different kind of QA work. Arguably a more valuable one.&lt;/p&gt;

&lt;p&gt;I cover this in more depth in a free QA handbook — link in my profile if you're interested.&lt;/p&gt;

&lt;p&gt;Has anyone else been experimenting with AI-generated test cases? Curious whether the input quality pattern holds across different approaches — and what you've found the AI consistently gets wrong.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>productivity</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
