<?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: David Diaz</title>
    <description>The latest articles on DEV Community by David Diaz (@relaunchdept).</description>
    <link>https://dev.to/relaunchdept</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%2F4068266%2F47d6fec2-1d98-4109-b0e6-2fc595ccac2d.png</url>
      <title>DEV Community: David Diaz</title>
      <link>https://dev.to/relaunchdept</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/relaunchdept"/>
    <language>en</language>
    <item>
      <title>Eight landing-page checks before you launch</title>
      <dc:creator>David Diaz</dc:creator>
      <pubDate>Mon, 10 Aug 2026 15:00:04 +0000</pubDate>
      <link>https://dev.to/relaunchdept/eight-landing-page-checks-before-you-launch-16j0</link>
      <guid>https://dev.to/relaunchdept/eight-landing-page-checks-before-you-launch-16j0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AI disclosure:&lt;/strong&gt; This article was developed with AI assistance and reviewed against public tests and deterministic audit output.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A page can be technically live and still fail before a customer understands the offer. RELAUNCH DEPT. uses this short pre-launch pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Delivery
&lt;/h2&gt;

&lt;p&gt;Check the final HTTP status, redirect chain, HTTPS and mixed-content risk. A 200 response is necessary, not sufficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Search basics
&lt;/h2&gt;

&lt;p&gt;Verify the title, meta description, canonical URL, page language and mobile viewport. Missing metadata makes a finished product look temporary.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Social previews
&lt;/h2&gt;

&lt;p&gt;Inspect the Open Graph title, description and image, plus Twitter card metadata. The first impression often happens before the visit.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Heading structure
&lt;/h2&gt;

&lt;p&gt;Use one useful H1 that explains the page. A logo, placeholder or decorative slogan is not a substitute.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Images
&lt;/h2&gt;

&lt;p&gt;Give meaningful images useful alt text and mark decorative images intentionally empty. This is a basic quality check, not an accessibility certification.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Trust leaks
&lt;/h2&gt;

&lt;p&gt;Search for lorem ipsum, TODO, “coming soon,” example domains and unfinished copy. One visible placeholder can undermine the rest of the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Structured data and favicon
&lt;/h2&gt;

&lt;p&gt;These are small omissions, but they are also visible signals of an incomplete launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Conversion path
&lt;/h2&gt;

&lt;p&gt;Give the visitor one clear next action instead of five competing buttons.&lt;/p&gt;

&lt;h2&gt;
  
  
  A reproducible result
&lt;/h2&gt;

&lt;p&gt;A public test against &lt;code&gt;example.com&lt;/code&gt; returned HTTP 200 but scored &lt;strong&gt;39/F with eight findings&lt;/strong&gt;. The useful reminder is simple: “loads successfully” is not the same as “ready to launch.”&lt;/p&gt;

&lt;p&gt;I turned this checklist into a bounded open-source Apify Actor. It accepts at most 10 public HTTP(S) URLs, performs one HTML request per page, follows no more than five validated redirects, blocks private or reserved networks and credential-bearing URLs, caps responses at 2 MB, and never logs in or bypasses access controls.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://apify.com/relaunch_dept/launch-qa-auditor/examples/pre-launch-landing-page-qa-audit" rel="noopener noreferrer"&gt;Try the reproducible public audit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ceodaradigu/launch-qa-auditor" rel="noopener noreferrer"&gt;Inspect the open-source implementation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the report exposes a positioning or conversion problem, RELAUNCH DEPT. offers two bounded one-time repair scopes: a &lt;a href="https://www.daradigu.com/?utm_source=devto&amp;amp;utm_medium=organic&amp;amp;utm_campaign=launch_qa_guide#offers" rel="noopener noreferrer"&gt;$59 landing-page teardown or $249 launch rescue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What is the most common “technically live, commercially broken” launch defect you see?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The audit is deterministic rules-based analysis, not legal, security, accessibility-certification or search-ranking advice.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>testing</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why a SaaS Launch Gets Visits but No Signups</title>
      <dc:creator>David Diaz</dc:creator>
      <pubDate>Sat, 08 Aug 2026 13:33:26 +0000</pubDate>
      <link>https://dev.to/relaunchdept/why-a-saas-launch-gets-visits-but-no-signups-aei</link>
      <guid>https://dev.to/relaunchdept/why-a-saas-launch-gets-visits-but-no-signups-aei</guid>
      <description>&lt;h2&gt;
  
  
  A four-leak audit for founders who do not need more traffic yet
&lt;/h2&gt;

&lt;p&gt;Transparency: this article was prepared with AI assistance by RELAUNCH DEPT. The examples are illustrative, and the diagnostic framework is provided for general operational use.&lt;/p&gt;

&lt;p&gt;A quiet launch creates a tempting conclusion: not enough people saw it. Sometimes that is true. Often it is not the first problem.&lt;/p&gt;

&lt;p&gt;If visitors arrive and still do nothing, buying more traffic simply sends more people into the same unclear decision. Before you promote harder, audit four leaks: message, proof, buying path, and distribution fit.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The message leak
&lt;/h2&gt;

&lt;p&gt;A weak landing page usually describes the product category instead of the buyer's job.&lt;/p&gt;

&lt;p&gt;“An AI-powered platform that transforms your workflow” sounds polished, but it leaves four questions unanswered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who is it for?&lt;/li&gt;
&lt;li&gt;What painful task does it replace?&lt;/li&gt;
&lt;li&gt;What changes after using it?&lt;/li&gt;
&lt;li&gt;Why should that happen now?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try this test: remove the product name and logo. Could a reader still tell which specific person should care and what they can accomplish?&lt;/p&gt;

&lt;p&gt;A stronger hero does not need to explain every feature. It needs to earn the next scroll. Name one buyer, one expensive or frustrating job, one concrete outcome, and one next step.&lt;/p&gt;

&lt;p&gt;Instead of “Unlock the power of customer data,” try a structure such as: “Turn one hour of customer calls into six sales-ready objections your team can use today.”&lt;/p&gt;

&lt;p&gt;Specificity gives the visitor something to accept or reject. Vagueness only asks them to work harder.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The proof leak
&lt;/h2&gt;

&lt;p&gt;Claims are not proof. “Fast,” “accurate,” and “easy” are conclusions the seller wants the buyer to reach.&lt;/p&gt;

&lt;p&gt;Evidence helps them reach it independently.&lt;/p&gt;

&lt;p&gt;Useful proof can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a real before-and-after example;&lt;/li&gt;
&lt;li&gt;a short product walkthrough tied to one job;&lt;/li&gt;
&lt;li&gt;an output sample with sensitive data removed;&lt;/li&gt;
&lt;li&gt;a measured result with its source and date;&lt;/li&gt;
&lt;li&gt;a named customer statement you have permission to publish;&lt;/li&gt;
&lt;li&gt;a transparent limitation that shows where the product is not a fit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If there is no customer proof yet, do not invent it. Show the mechanism. A concrete input, transformation, and output is stronger than a wall of unsupported superlatives.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The buying-path leak
&lt;/h2&gt;

&lt;p&gt;Interest disappears when the next step feels larger than the promise.&lt;/p&gt;

&lt;p&gt;Common friction includes competing calls to action, hidden pricing, a required sales call for a simple purchase, unclear delivery timing, and a checkout that introduces a different product name or scope.&lt;/p&gt;

&lt;p&gt;Walk through the path as a stranger:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read the hero.&lt;/li&gt;
&lt;li&gt;Click the primary action.&lt;/li&gt;
&lt;li&gt;Compare the checkout with the page.&lt;/li&gt;
&lt;li&gt;Ask what happens immediately after payment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The offer, price, delivery window, revision policy, and next step should agree everywhere. Every contradiction creates a reason to postpone.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The distribution-fit leak
&lt;/h2&gt;

&lt;p&gt;More channels do not automatically create more qualified attention.&lt;/p&gt;

&lt;p&gt;A broad community may produce visits while reaching almost nobody who feels the problem today. A smaller directory, comparison page, technical guide, or marketplace category can outperform a large audience when the intent is closer to the job you solve.&lt;/p&gt;

&lt;p&gt;Track channels separately. At minimum, record the page, date, audience, message angle, visits, meaningful conversations, checkout clicks, and payments. Do not call impressions demand, and do not call clicks revenue.&lt;/p&gt;

&lt;p&gt;After a useful sample, keep the channels that create qualified actions and replace the ones that only create noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 15-minute decision
&lt;/h2&gt;

&lt;p&gt;Do not redesign everything at once. Score the four leaks and choose the weakest one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the message is unclear, rewrite the hero before buying traffic.&lt;/li&gt;
&lt;li&gt;If the promise is clear but untrusted, add evidence.&lt;/li&gt;
&lt;li&gt;If visitors understand and believe you but hesitate, simplify the buying path.&lt;/li&gt;
&lt;li&gt;If the page converts warm visitors but launch traffic is irrelevant, change distribution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RELAUNCH DEPT. has a free, no-email launch scorecard that turns this audit into ten quick questions: &lt;a href="https://www.daradigu.com/launch-scorecard?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=quiet_launch_audit_20260808" rel="noopener noreferrer"&gt;https://www.daradigu.com/launch-scorecard?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=quiet_launch_audit_20260808&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want the repair executed rather than diagnosed, the $249 48-hour Launch Rescue Sprint covers positioning, a production-ready hero, launch visuals, reusable copy, and focused distribution: &lt;a href="https://www.daradigu.com/?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=quiet_launch_audit_20260808#sprint" rel="noopener noreferrer"&gt;https://www.daradigu.com/?utm_source=dev&amp;amp;utm_medium=article&amp;amp;utm_campaign=quiet_launch_audit_20260808#sprint&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The goal is not a louder launch. It is a clearer decision for the right buyer.&lt;/p&gt;

</description>
      <category>saas</category>
      <category>startup</category>
      <category>marketing</category>
      <category>productivity</category>
    </item>
    <item>
      <title>AI Said “Ready.” Two Sources Disagreed. Here’s the Gate That Stopped It.</title>
      <dc:creator>David Diaz</dc:creator>
      <pubDate>Sat, 08 Aug 2026 06:32:56 +0000</pubDate>
      <link>https://dev.to/relaunchdept/your-ai-agent-said-done-what-would-prove-it-3kbh</link>
      <guid>https://dev.to/relaunchdept/your-ai-agent-said-done-what-would-prove-it-3kbh</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted disclosure: I used AI tools to help edit this article and the&lt;br&gt;
open-source project it describes. The architecture, tests, deployment evidence,&lt;br&gt;
and claim boundaries were reviewed against the public repository and live&lt;br&gt;
service before publication.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I created this piece of content for the purposes of entering the All Things&lt;br&gt;
Agentic Hackathon.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An autonomous agent can produce a confident status update long before the work&lt;br&gt;
is actually complete. A deployment command can exit successfully while the&lt;br&gt;
public endpoint still fails. A marketplace can display an opportunity that the&lt;br&gt;
authoritative issue has already closed. A generated report can look finished&lt;br&gt;
while one required source is stale.&lt;/p&gt;

&lt;p&gt;The problem is not that language models cannot reason. The problem is that&lt;br&gt;
“done” is a state transition, and state transitions need evidence.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://github.com/ceodaradigu/proofline-agent" rel="noopener noreferrer"&gt;Proofline&lt;/a&gt; to test a&lt;br&gt;
simple pattern: let the model interpret the task, but make a deterministic gate&lt;br&gt;
decide whether the evidence is sufficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate interpretation from acceptance
&lt;/h2&gt;

&lt;p&gt;Proofline divides the workflow into two layers.&lt;/p&gt;

&lt;p&gt;The agent layer uses Gemini 3.6 Flash and Google Agent Development Kit to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;interpret the task contract;&lt;/li&gt;
&lt;li&gt;identify the requirements that need proof;&lt;/li&gt;
&lt;li&gt;explain missing or contradictory evidence;&lt;/li&gt;
&lt;li&gt;call a narrowly scoped evaluation tool.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The verification layer then applies explicit rules. It does not ask the model&lt;br&gt;
whether the task &lt;em&gt;feels&lt;/em&gt; complete. It evaluates structured evidence and returns&lt;br&gt;
one of four states:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NEEDS_EVIDENCE&lt;/code&gt; — at least one requirement lacks fresh authoritative proof;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CONFLICT&lt;/code&gt; — authoritative sources contradict one another;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;APPROVAL_REQUIRED&lt;/code&gt; — the evidence is complete, but the next action has an
external side effect;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;READY&lt;/code&gt; — every requirement is satisfied and no approval gate remains.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That split matters. The model remains useful where language and context are&lt;br&gt;
messy, while the acceptance boundary stays inspectable and testable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make evidence a first-class object
&lt;/h2&gt;

&lt;p&gt;Each evidence item carries more than a sentence saying something worked. It&lt;br&gt;
records the requirement it supports, its source, whether that source is&lt;br&gt;
authoritative, when it was observed, and the value that was actually returned.&lt;/p&gt;

&lt;p&gt;A deployment claim, for example, should not be supported by “the command&lt;br&gt;
succeeded.” Better evidence is an external HTTP response from the deployed URL,&lt;br&gt;
the active revision identifier, and a timestamp inside the allowed freshness&lt;br&gt;
window.&lt;/p&gt;

&lt;p&gt;The same rule applies outside infrastructure. If a payment platform reports a&lt;br&gt;
test balance, it cannot prove live revenue. If a bounty marketplace says an&lt;br&gt;
issue is open but the repository says it is closed, the authoritative issue&lt;br&gt;
wins and the conflict should stop the workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hash the decision packet
&lt;/h2&gt;

&lt;p&gt;Once the gate evaluates the evidence, Proofline serializes the result in a&lt;br&gt;
canonical order and computes a SHA-256 packet hash. The hash does not make a&lt;br&gt;
weak claim true. It makes the exact decision inputs and output tamper-evident.&lt;/p&gt;

&lt;p&gt;This is useful when an agent runs asynchronously. A reviewer can verify that&lt;br&gt;
the packet being approved is the same packet the gate evaluated. If any&lt;br&gt;
requirement, evidence item, timestamp, or decision changes, the hash changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep external actions behind a human boundary
&lt;/h2&gt;

&lt;p&gt;Evidence can prove that a form is complete; it cannot decide whether a person&lt;br&gt;
wants to submit a legally binding entry, publish a message, or spend money.&lt;br&gt;
Proofline therefore treats those actions as a separate approval state.&lt;/p&gt;

&lt;p&gt;This prevents a common automation mistake: combining technical readiness with&lt;br&gt;
permission to act. The agent can prepare everything and prove that preparation,&lt;br&gt;
but the final side effect remains explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prove the architecture with a live path
&lt;/h2&gt;

&lt;p&gt;The public demonstration runs as a Google ADK application on Cloud Run. An&lt;br&gt;
external request can discover the &lt;code&gt;proofline&lt;/code&gt; app, create a real ADK session,&lt;br&gt;
invoke Gemini, and call the deterministic evaluation tool. The repository also&lt;br&gt;
contains a credential-free test path so the safety boundary can be inspected&lt;br&gt;
without cloud access.&lt;/p&gt;

&lt;p&gt;The deployed demo currently uses in-memory state. Firestore and Pub/Sub are&lt;br&gt;
documented extension points for durable packets and asynchronous rechecks; they&lt;br&gt;
are not presented as active components. That distinction is intentional:&lt;br&gt;
architecture diagrams should separate what is live from what is planned.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical checklist
&lt;/h2&gt;

&lt;p&gt;Before allowing an agent to declare a real task complete, ask:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What exact requirement is being satisfied?&lt;/li&gt;
&lt;li&gt;Which source is authoritative for that requirement?&lt;/li&gt;
&lt;li&gt;Is the observation fresh enough for the decision?&lt;/li&gt;
&lt;li&gt;What happens when two authoritative sources disagree?&lt;/li&gt;
&lt;li&gt;Can the decision be reproduced from structured inputs?&lt;/li&gt;
&lt;li&gt;Does the next step create an external side effect?&lt;/li&gt;
&lt;li&gt;Can a reviewer distinguish deployed components from planned ones?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If those questions do not have explicit answers, the agent probably has a&lt;br&gt;
status message, not proof.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch the contradiction happen in one continuous run
&lt;/h2&gt;

&lt;p&gt;The updated 46-second walkthrough uses one synthetic launch fixture from start to finish: Proofline collects the evidence, finds a 24-hour-versus-48-hour delivery contradiction, stops the action, verifies the correction against fresh sources, records human approval, and seals the evidence packet. No edit is used to hide a failing state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://daradigu.com/proofline?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=proofline_continuous_demo" rel="noopener noreferrer"&gt;Watch the continuous demo and inspect the evidence boundary&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also inspect the implementation, tests, architecture, and deployment evidence in the &lt;a href="https://github.com/ceodaradigu/proofline-agent" rel="noopener noreferrer"&gt;public Proofline repository&lt;/a&gt; or verify the &lt;a href="https://proofline-343140361830.europe-west1.run.app/list-apps" rel="noopener noreferrer"&gt;Cloud Run application discovery endpoint&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What failure mode should the next reproducible fixture cover? Leave it in the comments; concrete examples are more useful than generic feature requests.&lt;/p&gt;




&lt;p&gt;If you want an external evidence audit for a launch or automation, RELAUNCH DEPT. offers a &lt;a href="https://buy.stripe.com/bJe6oJ8PQ3lKgULaCrefC02?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=proofline_continuous_demo" rel="noopener noreferrer"&gt;USD 59 evidence audit&lt;/a&gt; and a &lt;a href="https://buy.stripe.com/00wcN75DE5tSfQH7qfefC00?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=proofline_continuous_demo" rel="noopener noreferrer"&gt;USD 249 implementation sprint&lt;/a&gt;. These are operational services, not legal, tax, or financial advice.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>agents</category>
      <category>showdev</category>
    </item>
    <item>
      <title>The JSON Error That Hid the Real Failure</title>
      <dc:creator>David Diaz</dc:creator>
      <pubDate>Sat, 08 Aug 2026 03:38:57 +0000</pubDate>
      <link>https://dev.to/relaunchdept/the-json-error-that-hid-the-real-failure-5da6</link>
      <guid>https://dev.to/relaunchdept/the-json-error-that-hid-the-real-failure-5da6</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Smash Stories&lt;/a&gt; powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A migration audit should fail loudly when data is lost. Mine failed loudly too—but, in one edge case, it reported the &lt;strong&gt;wrong failure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The bug lived in a one-command Python showcase built for an open-source Memanto contribution. The command turns a real GitHub discussion into an Open Knowledge Format bundle, runs Memanto's official migration dry run, round-trips the records through production mapping code, and writes a JSON fidelity receipt.&lt;/p&gt;

&lt;p&gt;The happy path was straightforward. The uncomfortable path was not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pipeline and its two kinds of failure
&lt;/h2&gt;

&lt;p&gt;The final audit is a subprocess. It can return a non-zero exit status for two very different reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;it completed the comparison and found lost or changed records, while still emitting a valid JSON receipt; or&lt;/li&gt;
&lt;li&gt;it crashed before it could emit valid JSON.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first case is expected domain behavior. We want to preserve its receipt and then propagate the non-zero status. The second is an operational failure. We want the original &lt;code&gt;CalledProcessError&lt;/code&gt;, including its exit code, because that is the evidence that tells a developer what actually went wrong.&lt;/p&gt;

&lt;p&gt;The original control flow captured the subprocess error, but then parsed its output before re-raising it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;audit_stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audit_command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CalledProcessError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;audit_error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
    &lt;span class="n"&gt;audit_stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;

&lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audit_stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;report_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That looked reasonable until the audit process failed without producing JSON. &lt;code&gt;json.loads()&lt;/code&gt; then raised &lt;code&gt;JSONDecodeError&lt;/code&gt; first. The original subprocess exception—and its meaningful return code—never reached the caller.&lt;/p&gt;

&lt;p&gt;The parser had become an error-mask.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproducing the hidden branch
&lt;/h2&gt;

&lt;p&gt;The useful breakthrough was to stop thinking of the output as simply “valid” or “invalid” and model two independent signals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did the process succeed?&lt;/li&gt;
&lt;li&gt;Is its output valid JSON?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That creates four cases:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Process result&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;th&gt;Correct behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;success&lt;/td&gt;
&lt;td&gt;valid JSON&lt;/td&gt;
&lt;td&gt;write receipt and continue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;failure&lt;/td&gt;
&lt;td&gt;valid JSON&lt;/td&gt;
&lt;td&gt;write receipt, then re-raise the process error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;failure&lt;/td&gt;
&lt;td&gt;invalid JSON&lt;/td&gt;
&lt;td&gt;re-raise the process error; do not create a receipt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;success&lt;/td&gt;
&lt;td&gt;invalid JSON&lt;/td&gt;
&lt;td&gt;surface &lt;code&gt;JSONDecodeError&lt;/code&gt; because the producer broke its contract&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The masked failure was the third row. A regression test simulated an audit that exited with status 7 and printed plain text instead of JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fake_run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;run_demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CalledProcessError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audit crashed before producing JSON&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;run_demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CompletedProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The test asserts two things that matter operationally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;run_demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_showcase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;acme/repo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workdir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;run_demo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CalledProcessError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;returncode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;AssertionError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid audit output masked the process failure&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workdir&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audit.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It does not merely expect “an exception.” It verifies that the &lt;strong&gt;right exception and exact status code survive&lt;/strong&gt;, and that invalid output is not blessed as an audit artifact.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: preserve causal priority
&lt;/h2&gt;

&lt;p&gt;The correction keeps valid failing receipts, but gives the original process failure priority when JSON parsing also fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;audit_stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt;

&lt;span class="n"&gt;report_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ensure_ascii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;audit_error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;from None&lt;/code&gt; is deliberate. In the simultaneous-failure branch, the JSON error is a side effect of missing output, not the root cause. Suppressing that context keeps the traceback focused on the subprocess failure the operator needs to investigate.&lt;/p&gt;

&lt;p&gt;At the same time, a valid JSON report from a fidelity failure is still written before the original non-zero result is propagated. That report is valuable evidence; throwing it away would create a different debugging problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed after the fix
&lt;/h2&gt;

&lt;p&gt;The branch now has explicit regression coverage for both failure modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a failed audit with valid JSON preserves the receipt and exit status;&lt;/li&gt;
&lt;li&gt;a failed audit with invalid output preserves the original exit status and writes no receipt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The focused suite reports 25 passing tests, with Ruff checks, formatting, and mypy also clean on the contribution branch. The wider migration demo has additionally completed a 32-record real-data round trip with zero removed or changed portable fields. Those broader results are useful, but the most important outcome of this debugging story is smaller: when the pipeline fails, its diagnostic contract is now trustworthy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three lessons I am keeping
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Error handling needs its own truth table
&lt;/h3&gt;

&lt;p&gt;Nested fallible operations create combinations that a linear happy-path reading hides. A small matrix exposed the missing branch faster than another end-to-end run would have.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Test identity, not just category
&lt;/h3&gt;

&lt;p&gt;“An exception was raised” would have passed before and after the fix. Checking &lt;code&gt;returncode == 7&lt;/code&gt; proves that causality survived.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Artifacts are part of failure semantics
&lt;/h3&gt;

&lt;p&gt;A diagnostic file should exist only when it is valid. The absence assertion prevents future code from leaving behind a misleading &lt;code&gt;audit.json&lt;/code&gt; after a producer crash.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evidence
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/moorcheh-ai/memanto/pull/1813" rel="noopener noreferrer"&gt;Open-source PR #1813&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/moorcheh-ai/memanto/blob/bb6ae2429d90663c96998a4f519ac3f8fe9fb079/examples/migrations/okf-portability-audit/run_demo.py" rel="noopener noreferrer"&gt;Current orchestrator code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/moorcheh-ai/memanto/blob/bb6ae2429d90663c96998a4f519ac3f8fe9fb079/examples/migrations/okf-portability-audit/tests/test_okf_audit.py" rel="noopener noreferrer"&gt;Regression tests&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The larger PR introduces an OKF portability workflow; this Smash Stories entry is specifically about the real exception-masking bug caught and fixed during its review. The PR is open and mergeable at the time of writing; no merge or bounty award is assumed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;AI assistance disclosure: AI tools assisted with code review and drafting. The behavior, fix, tests, and validation claims above are linked to reproducible repository evidence.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
      <category>python</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Five Mobile Landing-Page Bugs That Hide in Desktop Review</title>
      <dc:creator>David Diaz</dc:creator>
      <pubDate>Sat, 08 Aug 2026 03:28:24 +0000</pubDate>
      <link>https://dev.to/relaunchdept/five-mobile-landing-page-bugs-that-hide-in-desktop-review-20m0</link>
      <guid>https://dev.to/relaunchdept/five-mobile-landing-page-bugs-that-hide-in-desktop-review-20m0</guid>
      <description>&lt;p&gt;A practical pre-launch QA pass for 320 px, 375 px and 414 px screens.&lt;/p&gt;

&lt;p&gt;A landing page can look polished on a laptop and still lose customers on a phone. The problem is rarely one dramatic failure. It is usually five small defects that make the first action harder than it should be.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Horizontal overflow that only appears at one width
&lt;/h2&gt;

&lt;p&gt;Test at 320 px, 375 px and 414 px. Look for clipped copy, carousels wider than the viewport, fixed-width tables and decorative elements that push the page sideways. Record the exact viewport and attach a screenshot; “mobile is broken” is not an actionable bug report.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A primary CTA that disappears below the fold
&lt;/h2&gt;

&lt;p&gt;The visitor should understand the offer and see the primary action without hunting. Check whether a tall hero image, consent banner or oversized navigation moves the CTA below the first useful screen. The fix is often hierarchy, not more copy.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Touch targets that work with a mouse but not a thumb
&lt;/h2&gt;

&lt;p&gt;Buttons and links need enough space to tap reliably. Use 44 × 44 px as a practical minimum, then check the distance between adjacent controls. Tiny close icons, crowded navigation and text-only links are common failure points.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Forms that ignore the mobile keyboard
&lt;/h2&gt;

&lt;p&gt;Verify labels, focus order, error messages, autofill and the keyboard type for email, phone and numeric fields. A form can technically submit and still create enough friction to lose the conversion.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Images that steal the performance budget
&lt;/h2&gt;

&lt;p&gt;Inspect oversized hero images, off-screen media loaded too early and layout shifts caused by missing dimensions. The goal is not a perfect laboratory score; it is a stable first interaction on a real connection.&lt;/p&gt;

&lt;p&gt;A useful QA report should make every finding reproducible: viewport, steps, expected behaviour, actual behaviour, screenshot and priority. That format gives a designer or developer something they can fix immediately.&lt;/p&gt;

&lt;p&gt;I have packaged this process into a fixed-scope &lt;a href="https://contra.com/s/rMYEsYFv-mobile-landing-page-qa-audit" rel="noopener noreferrer"&gt;Mobile Landing Page QA Audit&lt;/a&gt;: one live page, annotated screenshots, a prioritized fix list and one retest, delivered within five business days for $59.&lt;/p&gt;

&lt;p&gt;AI-assisted tools may support analysis; every published finding is reviewed before delivery.&lt;/p&gt;

&lt;p&gt;Originally published by &lt;a href="https://medium.com/@relaunchdept/five-mobile-landing-page-bugs-that-hide-in-desktop-review-e574f4e6ccc8" rel="noopener noreferrer"&gt;RELAUNCH DEPT. on Medium&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>webdev</category>
      <category>ux</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
