<?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: Ricardo Diaz Miralles</title>
    <description>The latest articles on DEV Community by Ricardo Diaz Miralles (@ricardo_diazmiralles).</description>
    <link>https://dev.to/ricardo_diazmiralles</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%2F3907989%2F8bd936ab-5447-44a8-8309-f96aaccceee7.jpg</url>
      <title>DEV Community: Ricardo Diaz Miralles</title>
      <link>https://dev.to/ricardo_diazmiralles</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ricardo_diazmiralles"/>
    <language>en</language>
    <item>
      <title>The pre-publish image checklist: 7 things I verify before any image goes live</title>
      <dc:creator>Ricardo Diaz Miralles</dc:creator>
      <pubDate>Fri, 03 Jul 2026 22:44:18 +0000</pubDate>
      <link>https://dev.to/ricardo_diazmiralles/the-pre-publish-image-checklist-7-things-i-verify-before-any-image-goes-live-4h1h</link>
      <guid>https://dev.to/ricardo_diazmiralles/the-pre-publish-image-checklist-7-things-i-verify-before-any-image-goes-live-4h1h</guid>
      <description>&lt;p&gt;Every developer has shipped an image that was too heavy, wrongly sized, or worse: one that still had GPS coordinates buried in its EXIF data. I did it enough times that I ended up building a checklist, and eventually a set of free browser tools around it. Here is the checklist, with both manual ways to run each check and the shortcut.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Dimensions: is it the size it will actually display at?
&lt;/h2&gt;

&lt;p&gt;Serving a 4000px-wide photo in an 800px container wastes bandwidth and hurts LCP. Check the rendered size in DevTools (hover the img in the Elements panel) and compare it with the intrinsic size. As a rule of thumb, export at 1x and 2x of the display size and let srcset do the rest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"hero-800.webp"&lt;/span&gt;
     &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"hero-800.webp 1x, hero-1600.webp 2x"&lt;/span&gt;
     &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"800"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"450"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"..."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. File size: does it fit your budget?
&lt;/h2&gt;

&lt;p&gt;For most content images, aim for under ~150 KB; hero images can justify more. If you are on Node, sharp handles resizing and compression in one pass:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;sharp&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sharp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sharp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1600&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;webp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;78&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;toFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hero.webp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Format: WebP/AVIF unless you have a reason not to
&lt;/h2&gt;

&lt;p&gt;JPEG/PNG still make sense for compatibility corner cases, but WebP typically cuts 25-35% at equal quality, and AVIF more. Photographs: AVIF/WebP. Logos and flat art: SVG. Screenshots: WebP or PNG.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Metadata: strip what you don't want public
&lt;/h2&gt;

&lt;p&gt;This is the one people forget. Photos from phones carry EXIF: device model, timestamps, and often GPS location. Check what's inside with exiftool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;exiftool photo.jpg | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"gps|serial|owner"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Re-exporting through most build pipelines (sharp, imagemin) strips EXIF, but images uploaded straight to a CMS often keep it.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Filename and alt text: the SEO part
&lt;/h2&gt;

&lt;p&gt;IMG_4032.jpg tells search engines nothing. blue-running-shoes-side-view.webp does. Same for alt text: describe the image for someone who can't see it. That serves accessibility first and image SEO as a side effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Social readiness: will the crop survive each platform?
&lt;/h2&gt;

&lt;p&gt;The same source image gets cropped differently by Open Graph previews (1.91:1), Instagram (4:5 or 1:1), YouTube thumbnails (16:9 with TV-safe margins)... If a campaign matters, prepare dedicated crops. I keep a &lt;a href="https://publishpixel.net/social-media-image-sizes" rel="noopener noreferrer"&gt;cheat sheet of every platform's exact pixel sizes&lt;/a&gt; because they change every year.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Open Graph: does the preview actually render?
&lt;/h2&gt;

&lt;p&gt;Before sharing, verify og:image resolves, is at least 1200x630, and isn't blocked by robots. The classic way is the Meta Sharing Debugger or curl + eyeballing the tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://example.com | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;meta property="og:[^&amp;gt;]*&amp;gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The shortcut
&lt;/h2&gt;

&lt;p&gt;Running all seven checks by hand gets old fast. I built &lt;a href="https://publishpixel.net" rel="noopener noreferrer"&gt;PublishPixel&lt;/a&gt; to run them in one pass: you drop an image and it reports dimensions, weight, format fit, filename, alt-text plan, metadata (including GPS), and readiness for web/SEO/social/YouTube. Everything runs client-side in your browser: no upload, no account, files never leave your machine. It's free; it exists because of this checklist.&lt;/p&gt;

&lt;p&gt;Disclosure: PublishPixel is my project. The manual methods above work fine without it. The point is to run the checklist somehow before hitting publish.&lt;/p&gt;

&lt;p&gt;What would you add as check #8?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>performance</category>
      <category>beginners</category>
    </item>
    <item>
      <title>A warehouse supervisor's guide to shipping a SaaS in 3 weeks (with a lot of AI help)</title>
      <dc:creator>Ricardo Diaz Miralles</dc:creator>
      <pubDate>Fri, 01 May 2026 18:41:25 +0000</pubDate>
      <link>https://dev.to/ricardo_diazmiralles/a-warehouse-supervisors-guide-to-shipping-a-saas-in-3-weeks-with-a-lot-of-ai-help-4goi</link>
      <guid>https://dev.to/ricardo_diazmiralles/a-warehouse-supervisors-guide-to-shipping-a-saas-in-3-weeks-with-a-lot-of-ai-help-4goi</guid>
      <description>&lt;p&gt;Hey DEV community 👋&lt;/p&gt;

&lt;p&gt;I'm Ricardo. By day I run a warehouse in Boston, Lincolnshire (UK). By night, for the last few weeks, I've been building a SaaS with the help of AI tools — and as of this week, it's live in production with real Stripe payments.&lt;/p&gt;

&lt;p&gt;This post is partly an introduction, partly a "non-developer founder ships product in 2026" snapshot.&lt;/p&gt;

&lt;h2&gt;
  
  
  The product
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://fairtime.net" rel="noopener noreferrer"&gt;FairTime&lt;/a&gt; is a meeting scheduler that finds times across time zones and ranks options by &lt;strong&gt;attendance&lt;/strong&gt;, &lt;strong&gt;comfort&lt;/strong&gt;, and &lt;strong&gt;fairness&lt;/strong&gt; — so the same person doesn't always end up taking the 11pm or the 6am call.&lt;/p&gt;

&lt;p&gt;The reason it exists is personal. My family is scattered across Venezuela, the UK, and Spain. Every video call, someone is eating dinner late or waking up early. Almost always my mum. I wanted to build something that rotates the inconvenience instead of always defaulting to whoever complains less.&lt;/p&gt;

&lt;p&gt;Then I realised distributed teams have the same problem dressed up in calendar invites.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 16&lt;/strong&gt; (App Router, Turbopack) — frontend + API routes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe&lt;/strong&gt; — subscriptions, with two-layer anti-trial-abuse (email + card fingerprint)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turso (libSQL)&lt;/strong&gt; — edge database for fairness history and trial tracking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind + shadcn/ui&lt;/strong&gt; — UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Netlify&lt;/strong&gt; — hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bilingual EN/ES from day one — useful for hispano teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where AI fits in
&lt;/h2&gt;

&lt;p&gt;I am not a developer. I read code, I can edit it, I can spot when something looks wrong — but I can't write 800 lines of TypeScript from scratch. AI tools (Claude in particular) have done most of the heavy lifting on the code I couldn't write myself.&lt;/p&gt;

&lt;p&gt;What I bring: product judgement, the actual problem, attention to detail, and the willingness to push back when the AI suggests something wrong or over-engineered.&lt;/p&gt;

&lt;p&gt;What I learned: AI doesn't replace understanding. The bugs I spent the most time on were the ones where I trusted the AI's first answer instead of pushing it to explain why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I am right now
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Started early April 2026&lt;/li&gt;
&lt;li&gt;Solo founder, no investors&lt;/li&gt;
&lt;li&gt;No paying users yet (the honest number)&lt;/li&gt;
&lt;li&gt;Stripe live, anti-trial-abuse layered, OAuth verification with Google in progress&lt;/li&gt;
&lt;li&gt;Just submitted to Capterra, working on getting indexed properly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I'd love from you
&lt;/h2&gt;

&lt;p&gt;Honest, technical feedback on the landing page. Specifically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Does the value prop land in the first 5 seconds, or do you bounce?&lt;/li&gt;
&lt;li&gt;Is the pricing page clear, or does anything feel sketchy?&lt;/li&gt;
&lt;li&gt;What's the dumbest thing you'd remove?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The free tier needs no signup, so testing the actual planner costs nothing.&lt;/p&gt;

&lt;p&gt;Also genuinely curious — anyone else here building without being a "real" developer? How do you handle the fear of imposter syndrome at 11pm when something breaks in production?&lt;/p&gt;

&lt;p&gt;Cheers from a small town in Lincolnshire 🙏&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://fairtime.net" rel="noopener noreferrer"&gt;https://fairtime.net&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
