<?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: Christopher H. Dutra</title>
    <description>The latest articles on DEV Community by Christopher H. Dutra (@christopher-dutra).</description>
    <link>https://dev.to/christopher-dutra</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%2F4201792%2F48d82f5d-cd46-4bd6-9634-450e958aa285.png</url>
      <title>DEV Community: Christopher H. Dutra</title>
      <link>https://dev.to/christopher-dutra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/christopher-dutra"/>
    <language>en</language>
    <item>
      <title>The 10-Minute Race: Designing Email Verification That Doesn't Frustrate Users</title>
      <dc:creator>Christopher H. Dutra</dc:creator>
      <pubDate>Fri, 23 Oct 2026 10:33:05 +0000</pubDate>
      <link>https://dev.to/christopher-dutra/the-10-minute-race-designing-email-verification-that-doesnt-frustrate-users-2hn7</link>
      <guid>https://dev.to/christopher-dutra/the-10-minute-race-designing-email-verification-that-doesnt-frustrate-users-2hn7</guid>
      <description>&lt;p&gt;You know the experience: you sign up, switch to your inbox, refresh twice, finally see the verification email... and discover the link has expired.&lt;/p&gt;

&lt;p&gt;It's frustrating because the product is telling you to complete a task and then punishing you for not completing it quickly enough.&lt;/p&gt;

&lt;p&gt;Email verification sits at the intersection of backend security, delivery delays, and interface design. You need all three parts to cooperate.&lt;/p&gt;

&lt;h2&gt;
  
  
  There are actually two clocks
&lt;/h2&gt;

&lt;p&gt;If you use a short-lived mailbox during QA, you'll see this clearly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mailbox clock:&lt;/strong&gt; how long the destination can receive and display messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verification clock:&lt;/strong&gt; how long your application's link or one-time code stays valid.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those values are independent.&lt;/p&gt;

&lt;p&gt;A message can still be visible after its verification token expires. Or the token could be valid while the temporary inbox that received it is already gone.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="https://10mintempemail.com/" rel="noopener noreferrer"&gt;10 Minute Temp Email&lt;/a&gt; creates receive-only inboxes that expire after ten minutes.&lt;/p&gt;

&lt;p&gt;That says nothing about the lifespan of tokens generated by your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't let the browser invent authority
&lt;/h2&gt;

&lt;p&gt;A countdown makes a nice interface, but security must be enforced by the backend.&lt;/p&gt;

&lt;p&gt;You might display the remaining time like this:&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="c1"&gt;// For display only: the server remains authoritative.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;remainingMs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&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;span class="nx"&gt;expiresAt&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;remainingSeconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remainingMs&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual verification endpoint still needs to check token validity on the server.&lt;/p&gt;

&lt;p&gt;It should also decide what happens when the token has already been used.&lt;/p&gt;

&lt;p&gt;Client time can be wrong, tabs can sleep, and network delays can shift what people see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design the resend flow before users need it
&lt;/h2&gt;

&lt;p&gt;A good verification screen should answer a few basic questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which address did we send the message to?&lt;/li&gt;
&lt;li&gt;Can the user correct a typo?&lt;/li&gt;
&lt;li&gt;When is it reasonable to request another message?&lt;/li&gt;
&lt;li&gt;Will requesting a new email invalidate the previous link?&lt;/li&gt;
&lt;li&gt;What happens if both messages arrive out of order?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The resend button should be visible, but not an invitation to flood inboxes.&lt;/p&gt;

&lt;p&gt;Apply server-side rate limiting and show a clear cooldown if needed.&lt;/p&gt;

&lt;p&gt;Most importantly, decide whether old tokens remain valid after a resend.&lt;/p&gt;

&lt;p&gt;Either policy can be implemented, but the behavior should be intentional, tested, and documented.&lt;/p&gt;

&lt;h2&gt;
  
  
  The tests I would not skip
&lt;/h2&gt;

&lt;p&gt;I like to run these scenarios in staging:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify immediately after signup.&lt;/li&gt;
&lt;li&gt;Wait until the token expires, then click the link.&lt;/li&gt;
&lt;li&gt;Request a resend and use the newest message.&lt;/li&gt;
&lt;li&gt;Click a successful link a second time.&lt;/li&gt;
&lt;li&gt;Change the email address during verification.&lt;/li&gt;
&lt;li&gt;Delay email delivery and check the on-screen instructions.&lt;/li&gt;
&lt;li&gt;Open the link on a different device, if your flow supports it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For authorized manual tests, a temporary inbox helps make these loops repeatable without sending every attempt into a personal mailbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the language human
&lt;/h2&gt;

&lt;p&gt;A message like &lt;code&gt;TOKEN_EXPIRED&lt;/code&gt; is useful in your logs. It isn't much help to a person who just wants to finish creating an account.&lt;/p&gt;

&lt;p&gt;I'd rather show:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This verification link has expired. Request a new email to continue.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And after resending:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We sent a new link. Check your inbox, including spam or junk, and use the latest message.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Clear copy is a small feature that removes a surprising amount of support friction.&lt;/p&gt;

&lt;h2&gt;
  
  
  The broader lesson
&lt;/h2&gt;

&lt;p&gt;Email verification shouldn't require perfect timing.&lt;/p&gt;

&lt;p&gt;It should remain secure while giving ordinary users a reasonable path through delayed messages, mistyped addresses, and expired links.&lt;/p&gt;

&lt;p&gt;Test the clock, test the email, and test the recovery experience. All three are part of the feature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's one thing you'd change about the last verification flow you built?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>authentication</category>
      <category>backend</category>
      <category>design</category>
      <category>security</category>
    </item>
    <item>
      <title>Temporary Email, Email Alias, or a Real Inbox? A Developer's Decision Guide</title>
      <dc:creator>Christopher H. Dutra</dc:creator>
      <pubDate>Fri, 23 Oct 2026 10:25:27 +0000</pubDate>
      <link>https://dev.to/christopher-dutra/temporary-email-email-alias-or-a-real-inbox-a-developers-decision-guide-17ah</link>
      <guid>https://dev.to/christopher-dutra/temporary-email-email-alias-or-a-real-inbox-a-developers-decision-guide-17ah</guid>
      <description>&lt;p&gt;I used to think the choice was simple: either use my main email address or use a fake one.&lt;/p&gt;

&lt;p&gt;In reality, there are at least three useful categories, and they solve different problems: a permanent inbox, a forwarding alias, and a disposable inbox.&lt;/p&gt;

&lt;p&gt;Mixing them up creates avoidable trouble—especially when an account that seemed temporary turns into one you actually care about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three tools, three jobs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;th&gt;Can you come back later?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Permanent inbox&lt;/td&gt;
&lt;td&gt;Work, important accounts, recovery&lt;/td&gt;
&lt;td&gt;Yes, if you retain access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email alias&lt;/td&gt;
&lt;td&gt;Accounts you may keep, with address separation&lt;/td&gt;
&lt;td&gt;Usually, while forwarding remains configured&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Temporary inbox&lt;/td&gt;
&lt;td&gt;One-time inbound messages and short authorized tests&lt;/td&gt;
&lt;td&gt;No, once it expires&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The key question isn't, "Which address hides me the most?"&lt;/p&gt;

&lt;p&gt;It's &lt;strong&gt;"Will I need to receive another email at this address next month?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the answer is yes, a ten-minute inbox is probably the wrong option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scenario 1: Testing a signup flow
&lt;/h2&gt;

&lt;p&gt;You're working on a staging environment, and every registration sends a confirmation link.&lt;/p&gt;

&lt;p&gt;You need a fresh destination, you need to read the message once, and you can delete the test account afterwards.&lt;/p&gt;

&lt;p&gt;A temporary receive-only inbox can be a nice fit, provided your staging application allows disposable domains.&lt;/p&gt;

&lt;p&gt;A service like &lt;a href="https://10mintempemail.com/" rel="noopener noreferrer"&gt;10 Minute Temp Email&lt;/a&gt; creates an inbox without a permanent account and ends access after ten minutes.&lt;/p&gt;

&lt;p&gt;That limited lifespan is useful precisely because the test doesn't need to become a new identity you maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scenario 2: Signing up for a tool you might keep
&lt;/h2&gt;

&lt;p&gt;Maybe it's a design service, a monitoring dashboard, or a newsletter with an account you expect to use again.&lt;/p&gt;

&lt;p&gt;An email alias is often smarter than a short-lived inbox.&lt;/p&gt;

&lt;p&gt;Mail still reaches an address you control, and you can receive login codes, invoices, or recovery links in the future.&lt;/p&gt;

&lt;p&gt;The alias also helps you understand which service sent a message or exposed an address, although it doesn't automatically make the entire account anonymous.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scenario 3: Banking, employment, and important accounts
&lt;/h2&gt;

&lt;p&gt;Use an address you can reliably access and recover.&lt;/p&gt;

&lt;p&gt;This isn't an area to optimize for maximum disposability.&lt;/p&gt;

&lt;p&gt;You may need statements, security alerts, legal notices, or a password-reset message months later.&lt;/p&gt;

&lt;p&gt;A temporary address would turn a small privacy preference into a serious account-recovery risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about spam protection?
&lt;/h2&gt;

&lt;p&gt;Disposable mail can reduce how often your &lt;strong&gt;primary address&lt;/strong&gt; is shared.&lt;/p&gt;

&lt;p&gt;Aliases can help you compartmentalize services and disable a troublesome address without abandoning your primary inbox.&lt;/p&gt;

&lt;p&gt;Neither stops all tracking, phishing, or misuse of information you enter elsewhere. Email is only one piece of your digital footprint.&lt;/p&gt;

&lt;p&gt;And if a service rejects disposable domains, respect that rule. Don't treat the block as a puzzle to defeat.&lt;/p&gt;

&lt;h2&gt;
  
  
  My practical rule
&lt;/h2&gt;

&lt;p&gt;Before entering an email address anywhere, ask:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do I trust this service enough to maintain an account?&lt;/li&gt;
&lt;li&gt;Will I need password recovery, receipts, or follow-up emails?&lt;/li&gt;
&lt;li&gt;Is this a short-lived task where disposable mail is explicitly allowed?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the account matters, use a durable address.&lt;/p&gt;

&lt;p&gt;If it might matter later, use an alias.&lt;/p&gt;

&lt;p&gt;If it's a truly disposable, low-stakes inbound task, use a short-lived inbox.&lt;/p&gt;

&lt;p&gt;That simple distinction saves more headaches than any inbox-cleaning trick.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you organize email addresses for development tools and test accounts?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>HTML Emails Are Untrusted Input. Your Inbox UI Should Treat Them That Way.</title>
      <dc:creator>Christopher H. Dutra</dc:creator>
      <pubDate>Fri, 23 Oct 2026 10:24:12 +0000</pubDate>
      <link>https://dev.to/christopher-dutra/html-emails-are-untrusted-input-your-inbox-ui-should-treat-them-that-way-2af2</link>
      <guid>https://dev.to/christopher-dutra/html-emails-are-untrusted-input-your-inbox-ui-should-treat-them-that-way-2af2</guid>
      <description>&lt;p&gt;Here's something easy to forget when building a web inbox: an email is not a page that you created.&lt;/p&gt;

&lt;p&gt;It is content supplied by somebody else, possibly somebody who would very much like your application to behave badly.&lt;/p&gt;

&lt;p&gt;That means showing an HTML email inside your app deserves roughly the same suspicion as rendering user-submitted HTML anywhere else.&lt;/p&gt;

&lt;h2&gt;
  
  
  A pretty preview can be a security problem
&lt;/h2&gt;

&lt;p&gt;Email HTML can contain images, links, inline styles, and deeply nested markup.&lt;/p&gt;

&lt;p&gt;Depending on how it is handled, it can also contain active elements or URLs you never intended to allow in your application.&lt;/p&gt;

&lt;p&gt;Even if your mail parser works perfectly, the next step—turning parsed HTML into a browser view—is a separate trust boundary.&lt;/p&gt;

&lt;p&gt;The dangerous shortcut is taking arbitrary message HTML and inserting it into the main application DOM as though it were trusted content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build layers instead of betting on one filter
&lt;/h2&gt;

&lt;p&gt;A safer pipeline looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Incoming MIME
    |
    v
Parse message parts
    |
    v
Sanitize HTML and limit sizes
    |
    v
Store permitted content
    |
    v
Sanitize again for display
    |
    v
Render in an isolated viewer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each step addresses a different concern.&lt;/p&gt;

&lt;p&gt;Parsing turns the MIME envelope into understandable parts. Sanitizing removes dangerous markup and attributes. Size limits prevent absurdly large content from overwhelming the system.&lt;/p&gt;

&lt;p&gt;An isolated viewer reduces the impact if something slips through.&lt;/p&gt;

&lt;p&gt;This is defense in depth, not a guarantee that every email is safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat attributes and URLs as input, too
&lt;/h2&gt;

&lt;p&gt;Stripping &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags alone doesn't solve the problem.&lt;/p&gt;

&lt;p&gt;Event-handler attributes, unsupported embedded elements, and unsafe URL schemes also matter.&lt;/p&gt;

&lt;p&gt;You also need to think about remote images.&lt;/p&gt;

&lt;p&gt;An innocuous-looking email can load a remote resource when opened. That request may reveal information to the sender, even when no script runs.&lt;/p&gt;

&lt;p&gt;A good viewer should make conscious decisions about remote content instead of treating every image URL as harmless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why plain text still matters
&lt;/h2&gt;

&lt;p&gt;A developer can spend an hour perfecting an HTML verification template and forget its text alternative.&lt;/p&gt;

&lt;p&gt;That's a mistake for accessibility, compatibility, and security-conscious readers.&lt;/p&gt;

&lt;p&gt;A confirmation message should still explain what to do when styles or images are blocked.&lt;/p&gt;

&lt;p&gt;For a signup email, I would check that the plain-text body contains the relevant explanation and a usable confirmation link or code.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real implementation worth studying
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://10mintempemail.com/" rel="noopener noreferrer"&gt;10 Minute Temp Email&lt;/a&gt; has a receive-only web inbox.&lt;/p&gt;

&lt;p&gt;Its published implementation notes describe server-side sanitization, a second browser-side pass with DOMPurify, and display inside a sandboxed iframe.&lt;/p&gt;

&lt;p&gt;It also limits the attachment types that can be stored.&lt;/p&gt;

&lt;p&gt;Those choices illustrate an important principle:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You don't have to trust the output of one layer just because that layer is yours.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The project goes into more detail in its &lt;a href="https://10mintempemail.com/blog/how-temporary-email-messages-are-sanitized/" rel="noopener noreferrer"&gt;email sanitization and deletion write-up&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security isn't only about scripts
&lt;/h2&gt;

&lt;p&gt;Even well-sanitized email can contain a convincing phishing message, a suspicious PDF, or a link to an attacker-controlled site.&lt;/p&gt;

&lt;p&gt;The interface still needs clear sender information, understandable link behavior, and honest warnings where appropriate.&lt;/p&gt;

&lt;p&gt;Security controls should make common mistakes less likely, not encourage people to click without thinking.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;The moment your application renders email, you've created a content-security feature whether you planned to or not.&lt;/p&gt;

&lt;p&gt;Treat the message body as untrusted data, preserve the safe content users actually need, and isolate the reader from the rest of your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What has been your hardest HTML sanitization edge case?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A Disposable Inbox Is a Surprisingly Interesting Serverless Design Problem</title>
      <dc:creator>Christopher H. Dutra</dc:creator>
      <pubDate>Fri, 23 Oct 2026 07:24:50 +0000</pubDate>
      <link>https://dev.to/christopher-dutra/a-disposable-inbox-is-a-surprisingly-interesting-serverless-design-problem-2c2l</link>
      <guid>https://dev.to/christopher-dutra/a-disposable-inbox-is-a-surprisingly-interesting-serverless-design-problem-2c2l</guid>
      <description>&lt;p&gt;A temporary email address sounds almost too simple to be a software project: generate a random string, accept some email, show it in a browser, and delete everything ten minutes later.&lt;/p&gt;

&lt;p&gt;Then you start asking questions.&lt;/p&gt;

&lt;p&gt;Who is allowed to read the messages? What happens when mail arrives at the exact moment the inbox expires? Where do attachments live? How do you delete the underlying data instead of just hiding the UI?&lt;/p&gt;

&lt;p&gt;Suddenly it's a neat little systems-design exercise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with a constraint: receive-only
&lt;/h2&gt;

&lt;p&gt;The first architectural decision I would make is not to build a miniature Gmail.&lt;/p&gt;

&lt;p&gt;A receive-only service needs to accept and display inbound messages. It doesn't need compose, reply, forwarding, or outbound SMTP.&lt;/p&gt;

&lt;p&gt;Every extra feature introduces operational and abuse risks that the core use case doesn't need.&lt;/p&gt;

&lt;p&gt;That's how &lt;a href="https://10mintempemail.com/" rel="noopener noreferrer"&gt;10 Minute Temp Email&lt;/a&gt; is designed: it handles short-lived inbound messages, but doesn't let users send or reply.&lt;/p&gt;

&lt;h2&gt;
  
  
  Split mail processing from the website
&lt;/h2&gt;

&lt;p&gt;One useful real-world reference is the site's published Cloudflare architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser
   |
   v
Web Worker ------&amp;gt; D1: metadata
   |
   v
Inbox UI

Email Routing
   |
   v
Mail Ingest Worker
   |
   +-------------&amp;gt; D1: metadata
   |
   +-------------&amp;gt; R2: message bodies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The web side creates a mailbox and exposes authenticated read/delete operations.&lt;/p&gt;

&lt;p&gt;The ingest Worker receives incoming mail through Cloudflare Email Routing, checks that the address is valid, parses the message, and stores the permitted content.&lt;/p&gt;

&lt;p&gt;Separating those responsibilities makes the design easier to reason about. A normal page request should never have to process a raw MIME message.&lt;/p&gt;

&lt;h2&gt;
  
  
  Expiration has to be enforced by the server
&lt;/h2&gt;

&lt;p&gt;A countdown in JavaScript is useful feedback, but it is &lt;strong&gt;not your security boundary&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the browser says an inbox has expired, your API must still reject further reads.&lt;/p&gt;

&lt;p&gt;If a message is delivered to an expired address, the ingest side must not quietly accept it just because the browser is no longer watching.&lt;/p&gt;

&lt;p&gt;A reasonable data model keeps an &lt;code&gt;expires_at&lt;/code&gt; timestamp for each mailbox.&lt;/p&gt;

&lt;p&gt;Every read and ingest operation checks that timestamp against server time. A scheduled cleanup process then removes database records and stored message objects.&lt;/p&gt;

&lt;p&gt;This distinction matters: &lt;em&gt;access expiration&lt;/em&gt; and &lt;em&gt;physical cleanup&lt;/em&gt; are related, but not the same operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your session is the mailbox key
&lt;/h2&gt;

&lt;p&gt;Making the generated email address the only secret would be a mistake.&lt;/p&gt;

&lt;p&gt;Addresses are visible to the services that send mail and could appear in logs.&lt;/p&gt;

&lt;p&gt;The safer pattern is to bind a mailbox to a browser session.&lt;/p&gt;

&lt;p&gt;In this example project, an HttpOnly cookie proves ownership, while an HMAC hash of the session token is stored in D1.&lt;/p&gt;

&lt;p&gt;That way, knowing someone's temporary address isn't enough to open their inbox.&lt;/p&gt;

&lt;p&gt;It's also why opening the same email address in a different browser won't magically give you access to its messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  The failure paths are the interesting part
&lt;/h2&gt;

&lt;p&gt;Think about these cases before writing the happy-path UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An email arrives seconds after expiration.&lt;/li&gt;
&lt;li&gt;The object store succeeds, but the database insert fails.&lt;/li&gt;
&lt;li&gt;The same message is delivered twice.&lt;/li&gt;
&lt;li&gt;Someone guesses random inbox addresses.&lt;/li&gt;
&lt;li&gt;A user tries to download an attachment from another session.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A robust implementation needs consistent checks, rollback or compensating cleanup, deduplication, and authorization on every attachment fetch.&lt;/p&gt;

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

&lt;p&gt;Tiny products can contain serious engineering lessons.&lt;/p&gt;

&lt;p&gt;A ten-minute inbox combines event-driven processing, ephemeral storage, authentication, cleanup, and untrusted content handling in a compact system.&lt;/p&gt;

&lt;p&gt;If you're curious about the exact components used by this particular service, its creator has documented the &lt;a href="https://10mintempemail.com/blog/how-we-built-a-receive-only-inbox/" rel="noopener noreferrer"&gt;receive-only inbox architecture&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you were building one, which part would you prototype first: ingest, session security, or expiration?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I Test Email Verification Without Filling My Personal Inbox</title>
      <dc:creator>Christopher H. Dutra</dc:creator>
      <pubDate>Fri, 23 Oct 2026 07:23:41 +0000</pubDate>
      <link>https://dev.to/christopher-dutra/how-i-test-email-verification-without-filling-my-personal-inbox-50fn</link>
      <guid>https://dev.to/christopher-dutra/how-i-test-email-verification-without-filling-my-personal-inbox-50fn</guid>
      <description>&lt;p&gt;There's a small but surprisingly annoying part of building signup flows: &lt;strong&gt;the emails&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The form looks fine. The database row exists. Your mail provider says the message was accepted. Then someone tries to register and discovers that the verification link is broken, the message arrived too late, or the resend button creates two valid codes.&lt;/p&gt;

&lt;p&gt;I've learned to treat email verification as its own feature, not as the final line of a signup ticket.&lt;/p&gt;

&lt;h2&gt;
  
  
  A clean inbox makes repeated testing easier
&lt;/h2&gt;

&lt;p&gt;For a quick manual check, I don't want to create a new permanent mailbox or keep adding &lt;code&gt;+test1&lt;/code&gt;, &lt;code&gt;+test2&lt;/code&gt;, and &lt;code&gt;+test3&lt;/code&gt; to my personal address.&lt;/p&gt;

&lt;p&gt;Those aliases can be useful, but eventually the inbox becomes a graveyard of test emails.&lt;/p&gt;

&lt;p&gt;A short-lived inbox is a reasonable option when I'm testing an app I own or am authorized to test, and the app permits disposable addresses.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="https://10mintempemail.com/" rel="noopener noreferrer"&gt;10 Minute Temp Email&lt;/a&gt; provides a receive-only inbox that lives for ten minutes, needs no account, and cannot recover old mail after it expires.&lt;/p&gt;

&lt;p&gt;It's not a replacement for a real mailbox or a mail-deliverability testing platform. It's simply useful for watching one test message arrive.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five-minute happy-path test
&lt;/h2&gt;

&lt;p&gt;Here's a small manual workflow I like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the temporary inbox &lt;strong&gt;before&lt;/strong&gt; submitting the signup form.&lt;/li&gt;
&lt;li&gt;Copy the generated address instead of typing it by hand.&lt;/li&gt;
&lt;li&gt;Submit the form on the staging site.&lt;/li&gt;
&lt;li&gt;Check that the message arrives, and read both its subject and body.&lt;/li&gt;
&lt;li&gt;Open the verification link. Confirm that the correct account becomes verified.&lt;/li&gt;
&lt;li&gt;Open the link again. It should not perform a second verification action.&lt;/li&gt;
&lt;li&gt;Delete the test account and inbox when finished.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That catches a lot more than checking whether an email-send function returned success.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I deliberately try to break
&lt;/h2&gt;

&lt;p&gt;The happy path is only the beginning. These are the cases I add before I consider the feature ready:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test&lt;/th&gt;
&lt;th&gt;What should happen&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Wrong or altered token&lt;/td&gt;
&lt;td&gt;Clear failure without revealing sensitive details&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expired token&lt;/td&gt;
&lt;td&gt;Friendly explanation and a safe resend path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reused verification link&lt;/td&gt;
&lt;td&gt;No repeated side effect&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resend requested twice&lt;/td&gt;
&lt;td&gt;Predictable handling of old and new tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delayed message&lt;/td&gt;
&lt;td&gt;UI explains what the user can do next&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Different browser&lt;/td&gt;
&lt;td&gt;Behavior matches the app's session requirements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTML blocked or stripped&lt;/td&gt;
&lt;td&gt;Plain-text email still contains the essential action&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One especially useful check is clicking the link &lt;em&gt;after&lt;/em&gt; the app's token expires. A mailbox's lifetime and your application's token lifetime are two different clocks.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small testing rule that pays off
&lt;/h2&gt;

&lt;p&gt;Keep the test environment unmistakably separate from production. Prefix subjects with &lt;code&gt;[STAGING]&lt;/code&gt;, avoid real customer data, and use accounts you can safely delete.&lt;/p&gt;

&lt;p&gt;Also, don't use a temporary mailbox to test whether messages land in Gmail's Primary tab or Outlook's junk folder. For that, you need real destination mailboxes and proper deliverability checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lesson
&lt;/h2&gt;

&lt;p&gt;A signup feature isn't finished when the server sends the email. It's finished when someone receives it, understands it, uses it successfully, and can recover from ordinary mistakes.&lt;/p&gt;

&lt;p&gt;A throwaway inbox helps make that last mile less tedious.&lt;/p&gt;

&lt;p&gt;For a more detailed checklist, the &lt;a href="https://10mintempemail.com/blog/test-signup-and-email-verification-flows/" rel="noopener noreferrer"&gt;temporary inbox signup-testing guide&lt;/a&gt; is a useful companion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the strangest email-verification bug you've had to debug?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>QR Codes Are More Useful Than You Think: Practical Ideas for Developers</title>
      <dc:creator>Christopher H. Dutra</dc:creator>
      <pubDate>Fri, 23 Oct 2026 06:57:44 +0000</pubDate>
      <link>https://dev.to/christopher-dutra/qr-codes-are-more-useful-than-you-think-practical-ideas-for-developers-4m6m</link>
      <guid>https://dev.to/christopher-dutra/qr-codes-are-more-useful-than-you-think-practical-ideas-for-developers-4m6m</guid>
      <description>&lt;p&gt;QR codes have been around for years, but they continue to appear in interesting places.&lt;/p&gt;

&lt;p&gt;Restaurant menus, WiFi networks, event tickets, product packaging, business cards, and even authentication workflows.&lt;/p&gt;

&lt;p&gt;From a developer's perspective, they're interesting because they provide a simple bridge between physical objects and digital experiences.&lt;/p&gt;

&lt;p&gt;Someone points a phone camera at a small square image, and suddenly they're visiting a website, opening an application, or accessing information.&lt;/p&gt;

&lt;p&gt;But there's a little more to QR codes than just converting a URL into black-and-white squares.&lt;/p&gt;

&lt;p&gt;Let's explore some useful applications and practical implementation details.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually happens when you scan a QR code?
&lt;/h2&gt;

&lt;p&gt;A QR code is a two-dimensional barcode that stores encoded data.&lt;/p&gt;

&lt;p&gt;The scanner reads its pattern and interprets the stored content.&lt;/p&gt;

&lt;p&gt;That content might be a website URL, a piece of text, a WiFi configuration, or contact information.&lt;/p&gt;

&lt;p&gt;An important distinction is that QR codes don't necessarily need an internet connection to be decoded.&lt;/p&gt;

&lt;p&gt;For example, a QR code containing plain text can be read locally.&lt;/p&gt;

&lt;p&gt;A QR code containing a website URL, however, generally requires a connection to access that website.&lt;/p&gt;

&lt;p&gt;Understanding the difference helps when deciding how to use QR codes in your applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Sharing website links
&lt;/h2&gt;

&lt;p&gt;Let's start with the most common use case.&lt;/p&gt;

&lt;p&gt;You have a website:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You generate a QR code containing that URL.&lt;/p&gt;

&lt;p&gt;When someone scans the code, their phone recognizes the link and offers to open it.&lt;/p&gt;

&lt;p&gt;Simple.&lt;/p&gt;

&lt;p&gt;But there are a few details worth considering.&lt;/p&gt;

&lt;p&gt;First, keep your URLs reasonably short.&lt;/p&gt;

&lt;p&gt;Longer URLs require more encoded data, which can produce denser QR codes.&lt;/p&gt;

&lt;p&gt;Dense codes may be more difficult to scan when printed at small sizes.&lt;/p&gt;

&lt;p&gt;Second, think about the destination.&lt;/p&gt;

&lt;p&gt;If the website isn't mobile-friendly, making access easier with a QR code won't create a good user experience.&lt;/p&gt;

&lt;p&gt;A QR code is only the entry point.&lt;/p&gt;

&lt;p&gt;The experience after scanning matters just as much.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. WiFi QR codes
&lt;/h2&gt;

&lt;p&gt;This is one of my favorite practical applications.&lt;/p&gt;

&lt;p&gt;Instead of telling someone a long WiFi password, you can let them scan a QR code.&lt;/p&gt;

&lt;p&gt;A commonly used WiFi QR payload looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WIFI:T:WPA;S:GuestNetwork;P:examplePassword;;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what the main parts represent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;T&lt;/code&gt; identifies the security type.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;S&lt;/code&gt; identifies the network name.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;P&lt;/code&gt; contains the password.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compatible phones can recognize this format and offer to connect to the network.&lt;/p&gt;

&lt;p&gt;It's useful for offices, meeting rooms, guest houses, and other places where visitors frequently need WiFi access.&lt;/p&gt;

&lt;p&gt;Just remember that anyone who can scan or decode the QR code may also recover the password.&lt;/p&gt;

&lt;p&gt;For public areas, use an appropriately isolated guest network rather than exposing credentials for your main internal network.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Contact cards and business details
&lt;/h2&gt;

&lt;p&gt;QR codes can also store contact information.&lt;/p&gt;

&lt;p&gt;One approach is to encode a vCard.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BEGIN:VCARD
VERSION:3.0
FN:Alex Smith
ORG:Example Studio
TEL:+15550101234
EMAIL:alex@example.com
END:VCARD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A compatible scanning application can interpret that information as contact details.&lt;/p&gt;

&lt;p&gt;Instead of manually typing someone's phone number and email address, a person can scan the code and save the contact.&lt;/p&gt;

&lt;p&gt;For business cards, conference badges, and networking events, this can be genuinely useful.&lt;/p&gt;

&lt;p&gt;It also reduces typing mistakes.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Generating QR codes with JavaScript
&lt;/h2&gt;

&lt;p&gt;You don't always need an external service to create QR codes.&lt;/p&gt;

&lt;p&gt;There are JavaScript libraries that generate QR codes directly inside applications.&lt;/p&gt;

&lt;p&gt;For example, using the &lt;code&gt;qrcode&lt;/code&gt; npm package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;qrcode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can generate an image like this:&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;QRCode&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;qrcode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrImage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;QRCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;errorCorrectionLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;H&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;qrImage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The returned data URL can be used as the source of an image element.&lt;/p&gt;

&lt;p&gt;For a production application, you could generate QR codes for tickets, user profiles, or other resources.&lt;/p&gt;

&lt;p&gt;One practical security note: if you're generating QR codes for authentication or access control, never rely on the QR image itself as proof of authorization. Use secure tokens, expiration rules, and server-side validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Creating QR codes with logos
&lt;/h2&gt;

&lt;p&gt;You've probably noticed QR codes that contain a company logo in the center.&lt;/p&gt;

&lt;p&gt;They look more branded, but adding a logo also introduces an interesting technical problem.&lt;/p&gt;

&lt;p&gt;The logo covers part of the QR code.&lt;/p&gt;

&lt;p&gt;How can the code still work?&lt;/p&gt;

&lt;p&gt;QR codes support error correction, which allows a scanner to recover data even when some parts are damaged or obscured.&lt;/p&gt;

&lt;p&gt;Common error-correction levels are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Approximate recovery capacity&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;L&lt;/td&gt;
&lt;td&gt;7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M&lt;/td&gt;
&lt;td&gt;15%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Q&lt;/td&gt;
&lt;td&gt;25%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H&lt;/td&gt;
&lt;td&gt;30%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are approximate recovery capacities, not guarantees that a logo can safely cover that percentage of the image.&lt;/p&gt;

&lt;p&gt;Logo placement, contrast, code density, and scanning conditions all matter.&lt;/p&gt;

&lt;p&gt;For branded QR codes, a higher error-correction level is often useful.&lt;/p&gt;

&lt;p&gt;Still, always test the final code on more than one device.&lt;/p&gt;

&lt;p&gt;A QR code that looks attractive but fails to scan isn't doing its job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating QR codes without writing code
&lt;/h2&gt;

&lt;p&gt;If you're building QR generation directly into an application, using a JavaScript library makes sense.&lt;/p&gt;

&lt;p&gt;But sometimes you only need a QR code for a presentation, website, event poster, or printed card.&lt;/p&gt;

&lt;p&gt;Writing code for a one-time image export would be unnecessary.&lt;/p&gt;

&lt;p&gt;That's where a browser-based generator is convenient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://imgtask.com/qr-code-generator" rel="noopener noreferrer"&gt;ImgTask's QR Code Generator&lt;/a&gt; supports URLs, text, WiFi configurations, email, phone numbers, SMS, and vCard information.&lt;/p&gt;

&lt;p&gt;You can customize colors, adjust error correction, add a logo, and export the result as PNG or SVG.&lt;/p&gt;

&lt;p&gt;The generation happens inside the browser, without uploading the content or logo to ImgTask's server.&lt;/p&gt;

&lt;p&gt;SVG is particularly useful when you want a scalable QR image for print or larger designs.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few mistakes worth avoiding
&lt;/h2&gt;

&lt;p&gt;Even though QR codes are simple to generate, there are some common issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using poor contrast:&lt;/strong&gt; Light-colored modules on a busy background may be difficult to scan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Removing too much whitespace:&lt;/strong&gt; QR codes need a clear quiet zone around the pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Making them too small:&lt;/strong&gt; A QR code on a poster should be large enough to scan comfortably from the intended distance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using unnecessarily long URLs:&lt;/strong&gt; More encoded data often means a denser pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skipping real-world testing:&lt;/strong&gt; A code that scans perfectly on your monitor might behave differently when printed.&lt;/p&gt;

&lt;p&gt;My preference is to generate the code, test it on two different phones, and then check the final design before using it publicly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;QR codes aren't complicated technology, but they're surprisingly flexible.&lt;/p&gt;

&lt;p&gt;They can help connect websites with physical products, simplify WiFi sharing, distribute contact information, and improve event workflows.&lt;/p&gt;

&lt;p&gt;For developers, the interesting part is deciding where QR codes actually improve an experience.&lt;/p&gt;

&lt;p&gt;Not every feature needs a QR code.&lt;/p&gt;

&lt;p&gt;But when scanning removes unnecessary steps for the user, it can be a genuinely useful addition.&lt;/p&gt;

&lt;p&gt;What's the most interesting way you've used QR codes in one of your applications?&lt;/p&gt;

</description>
      <category>programming</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>One Logo, Multiple Icon Sizes: Preparing App Icons for Android and iOS</title>
      <dc:creator>Christopher H. Dutra</dc:creator>
      <pubDate>Fri, 23 Oct 2026 06:55:36 +0000</pubDate>
      <link>https://dev.to/christopher-dutra/one-logo-multiple-icon-sizes-preparing-app-icons-for-android-and-ios-4i2e</link>
      <guid>https://dev.to/christopher-dutra/one-logo-multiple-icon-sizes-preparing-app-icons-for-android-and-ios-4i2e</guid>
      <description>&lt;p&gt;Building a mobile application involves dozens of small tasks beyond writing code.&lt;/p&gt;

&lt;p&gt;Authentication, navigation, APIs, notifications, permissions, and testing usually get most of our attention.&lt;/p&gt;

&lt;p&gt;Then, as the application gets closer to release, we remember something else.&lt;/p&gt;

&lt;p&gt;We need the app icons.&lt;/p&gt;

&lt;p&gt;Not just one icon, either.&lt;/p&gt;

&lt;p&gt;Android and iOS have different requirements, and preparing the necessary image files can become surprisingly repetitive.&lt;/p&gt;

&lt;p&gt;Let's look at how app icons work and how to simplify the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why can't we just use one PNG?
&lt;/h2&gt;

&lt;p&gt;Imagine you've designed a beautiful 1024 × 1024 pixel logo for your application.&lt;/p&gt;

&lt;p&gt;It looks great.&lt;/p&gt;

&lt;p&gt;So why can't you just add that PNG to your project and let the operating system handle everything?&lt;/p&gt;

&lt;p&gt;Technically, platforms and development tools can resize images. But mobile application projects typically expect assets organized according to platform-specific conventions.&lt;/p&gt;

&lt;p&gt;Android supports different screen densities and uses resources such as &lt;code&gt;mipmap-mdpi&lt;/code&gt;, &lt;code&gt;mipmap-hdpi&lt;/code&gt;, and others.&lt;/p&gt;

&lt;p&gt;iOS projects commonly use an asset catalog containing an &lt;code&gt;AppIcon&lt;/code&gt; image set.&lt;/p&gt;

&lt;p&gt;Providing appropriately sized assets helps ensure that your application icon looks consistent across supported devices.&lt;/p&gt;

&lt;p&gt;It also makes the project easier to manage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Android icon sizes
&lt;/h2&gt;

&lt;p&gt;Android traditionally organizes launcher icon resources by screen density.&lt;/p&gt;

&lt;p&gt;A common set of launcher icon sizes looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Density&lt;/th&gt;
&lt;th&gt;Icon size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mdpi&lt;/td&gt;
&lt;td&gt;48 × 48&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hdpi&lt;/td&gt;
&lt;td&gt;72 × 72&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xhdpi&lt;/td&gt;
&lt;td&gt;96 × 96&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xxhdpi&lt;/td&gt;
&lt;td&gt;144 × 144&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xxxhdpi&lt;/td&gt;
&lt;td&gt;192 × 192&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A typical Android resource directory might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/src/main/res/
├── mipmap-mdpi/
│   └── ic_launcher.png
├── mipmap-hdpi/
│   └── ic_launcher.png
├── mipmap-xhdpi/
│   └── ic_launcher.png
├── mipmap-xxhdpi/
│   └── ic_launcher.png
└── mipmap-xxxhdpi/
    └── ic_launcher.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the Android manifest, the application may reference the icon like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;application&lt;/span&gt;
    &lt;span class="na"&gt;android:icon=&lt;/span&gt;&lt;span class="s"&gt;"@mipmap/ic_launcher"&lt;/span&gt;
    &lt;span class="na"&gt;android:label=&lt;/span&gt;&lt;span class="s"&gt;"@string/app_name"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/application&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, modern Android applications also commonly use adaptive icons.&lt;/p&gt;

&lt;p&gt;Adaptive icons have separate foreground and background layers, allowing Android launchers to apply different masks and shapes.&lt;/p&gt;

&lt;p&gt;A simple collection of PNG files doesn't automatically replace a correctly configured adaptive icon.&lt;/p&gt;

&lt;p&gt;For modern Android applications, developers should review adaptive icon requirements as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about iOS?
&lt;/h2&gt;

&lt;p&gt;Apple uses its own asset catalog system.&lt;/p&gt;

&lt;p&gt;In an Xcode project, you'll commonly encounter a directory named:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AppIcon.appiconset&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This contains icon assets and a &lt;code&gt;Contents.json&lt;/code&gt; file describing how those assets correspond to the relevant icon slots.&lt;/p&gt;

&lt;p&gt;Rather than manually referencing each icon in code, Xcode uses the asset catalog configuration.&lt;/p&gt;

&lt;p&gt;For App Store distribution, a 1024 × 1024 pixel icon is important.&lt;/p&gt;

&lt;p&gt;One detail to remember: the App Store icon should not contain transparency. If you're starting with a transparent logo, prepare a version with an appropriate opaque background.&lt;/p&gt;

&lt;p&gt;The platform handles the final icon presentation, including corner treatment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing a good source image
&lt;/h2&gt;

&lt;p&gt;Before generating all the required sizes, focus on the original design.&lt;/p&gt;

&lt;p&gt;Ideally, start with a high-resolution square image.&lt;/p&gt;

&lt;p&gt;For example, 1024 × 1024 pixels is a useful starting point.&lt;/p&gt;

&lt;p&gt;Here are a few practical design considerations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep it simple.&lt;/strong&gt; A detailed illustration may look great at full resolution but become difficult to recognize on a home screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leave some breathing room.&lt;/strong&gt; Avoid placing important visual elements too close to the edges, where platform-specific masking may affect them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think about contrast.&lt;/strong&gt; The icon should remain recognizable against a variety of wallpapers and interface themes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test at small sizes.&lt;/strong&gt; Don't make design decisions using only the large original image.&lt;/p&gt;

&lt;p&gt;These considerations matter more than squeezing extra visual detail into the icon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generating the files without repetitive resizing
&lt;/h2&gt;

&lt;p&gt;You can prepare all these assets using design software or platform-specific development tools.&lt;/p&gt;

&lt;p&gt;Android Studio, for example, includes Image Asset Studio for creating icons.&lt;/p&gt;

&lt;p&gt;But when you're working across multiple projects, a straightforward icon generator can save manual work.&lt;/p&gt;

&lt;p&gt;One option is the &lt;a href="https://imgtask.com/app-icon-pack-generator" rel="noopener noreferrer"&gt;ImgTask App Icon Pack Generator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You upload a square logo, and it creates a downloadable ZIP containing Android launcher PNG sizes and an iOS &lt;code&gt;AppIcon.appiconset&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;The generated package includes Android mipmap folders, a Play Store icon, and iOS icon assets with a &lt;code&gt;Contents.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Image processing happens locally in the browser.&lt;/p&gt;

&lt;p&gt;For a standard raster icon workflow, this can reduce the time spent preparing repetitive asset sizes.&lt;/p&gt;

&lt;p&gt;You should still review the exported assets and make any platform-specific adjustments required by your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple release checklist
&lt;/h2&gt;

&lt;p&gt;Before publishing your mobile application, check that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your source logo is high resolution.&lt;/li&gt;
&lt;li&gt;The Android launcher icon looks sharp at different densities.&lt;/li&gt;
&lt;li&gt;Adaptive icons are configured if required.&lt;/li&gt;
&lt;li&gt;The iOS asset catalog contains the expected icon sizes.&lt;/li&gt;
&lt;li&gt;The App Store icon satisfies Apple's current requirements.&lt;/li&gt;
&lt;li&gt;The icon remains recognizable at small sizes.&lt;/li&gt;
&lt;li&gt;You've tested the icon on actual devices or emulators.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also make sure your application's icon visually matches its store listing and brand identity.&lt;/p&gt;

&lt;p&gt;Consistency matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Generating mobile app icons isn't particularly complicated, but it can be a repetitive part of the development process.&lt;/p&gt;

&lt;p&gt;Once you've built a few mobile applications, you start appreciating small workflow improvements.&lt;/p&gt;

&lt;p&gt;Whether you use Android Studio, Xcode, a design tool, or an online generator, the underlying goal is the same.&lt;/p&gt;

&lt;p&gt;Start with a good source image, prepare the assets correctly, and test the final icon where users will actually see it.&lt;/p&gt;

&lt;p&gt;A great app deserves an icon that feels just as polished.&lt;/p&gt;

&lt;p&gt;How do you handle app icon generation in your projects? Do you use platform-specific tools or generate the assets separately?&lt;/p&gt;

</description>
      <category>android</category>
      <category>ios</category>
      <category>mobile</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>The Small Website Detail Developers Often Forget: Favicons</title>
      <dc:creator>Christopher H. Dutra</dc:creator>
      <pubDate>Fri, 23 Oct 2026 06:52:08 +0000</pubDate>
      <link>https://dev.to/christopher-dutra/the-small-website-detail-developers-often-forget-favicons-30b7</link>
      <guid>https://dev.to/christopher-dutra/the-small-website-detail-developers-often-forget-favicons-30b7</guid>
      <description>&lt;p&gt;There's a particular moment in website development that feels familiar.&lt;/p&gt;

&lt;p&gt;The layout is finished. The contact form works. The mobile design looks good. You've connected the domain and deployed everything.&lt;/p&gt;

&lt;p&gt;Then you open the website in another browser tab.&lt;/p&gt;

&lt;p&gt;And there it is.&lt;/p&gt;

&lt;p&gt;A generic browser icon sitting next to your beautifully designed website's name.&lt;/p&gt;

&lt;p&gt;You forgot the favicon.&lt;/p&gt;

&lt;p&gt;It's a tiny detail, but it's one of those finishing touches that makes a website feel complete.&lt;/p&gt;

&lt;p&gt;The interesting part is that creating a proper favicon setup involves a little more than just uploading one image.&lt;/p&gt;

&lt;h2&gt;
  
  
  What exactly is a favicon?
&lt;/h2&gt;

&lt;p&gt;A favicon is the small icon associated with a website.&lt;/p&gt;

&lt;p&gt;You'll commonly see it in browser tabs, bookmarks, browser history, and certain shortcut interfaces.&lt;/p&gt;

&lt;p&gt;Its main purpose is recognition.&lt;/p&gt;

&lt;p&gt;When someone has fifteen tabs open, a recognizable favicon can make it easier to find your website.&lt;/p&gt;

&lt;p&gt;It also reinforces visual consistency between your website, logo, and overall brand.&lt;/p&gt;

&lt;p&gt;The favicon may only occupy a few pixels, but those pixels are visible in places where your full logo isn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why uploading a random logo isn't ideal
&lt;/h2&gt;

&lt;p&gt;Suppose your company has a beautiful horizontal logo with a company name and an illustration.&lt;/p&gt;

&lt;p&gt;You upload it as a favicon.&lt;/p&gt;

&lt;p&gt;The browser reduces it to 16 × 16 pixels.&lt;/p&gt;

&lt;p&gt;Suddenly, the text is unreadable, the illustration is blurry, and the whole thing becomes a tiny collection of shapes.&lt;/p&gt;

&lt;p&gt;That's why favicons should be designed for small display sizes.&lt;/p&gt;

&lt;p&gt;A good favicon often uses a simplified version of a logo.&lt;/p&gt;

&lt;p&gt;For example, instead of using your entire brand name, consider using its symbol or an easily recognizable initial.&lt;/p&gt;

&lt;p&gt;The goal isn't to fit everything inside a square.&lt;/p&gt;

&lt;p&gt;It's to make the brand recognizable at a very small size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which favicon sizes do you actually need?
&lt;/h2&gt;

&lt;p&gt;A useful basic favicon package includes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;favicon.ico&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Traditional browser compatibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;favicon-16x16.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Small browser icons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;favicon-32x32.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Higher-resolution browser icons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;apple-touch-icon.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Apple home-screen bookmarks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The traditional ICO format can contain multiple image sizes inside one file.&lt;/p&gt;

&lt;p&gt;A common combination is 16 × 16, 32 × 32, and 48 × 48 pixels.&lt;/p&gt;

&lt;p&gt;For Apple touch icons, 180 × 180 pixels is a widely used size.&lt;/p&gt;

&lt;p&gt;You don't necessarily need dozens of icon files for every project.&lt;/p&gt;

&lt;p&gt;A small, well-organized set is usually enough for a basic website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding favicon files to HTML
&lt;/h2&gt;

&lt;p&gt;Once you've generated the files, place them somewhere publicly accessible on your website.&lt;/p&gt;

&lt;p&gt;For a typical static website, that might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public/
├── favicon.ico
├── favicon-16x16.png
├── favicon-32x32.png
└── apple-touch-icon.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then reference them inside the HTML &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;:&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;link&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/favicon.ico"&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"any"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt;
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/png"&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"32x32"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/favicon-32x32.png"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt;
  &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/png"&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"16x16"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/favicon-16x16.png"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"apple-touch-icon"&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"180x180"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/apple-touch-icon.png"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser can select an appropriate supported resource.&lt;/p&gt;

&lt;p&gt;You can use the same approach in frameworks such as Astro, React-based static sites, and other projects that expose public assets.&lt;/p&gt;

&lt;p&gt;The exact folder structure depends on the framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about generating the favicon files?
&lt;/h2&gt;

&lt;p&gt;You can manually resize a logo, export several PNG files, and create an ICO file using image-editing software.&lt;/p&gt;

&lt;p&gt;But if you do this regularly for client websites, the repetitive export work becomes a little annoying.&lt;/p&gt;

&lt;p&gt;That's why tools that create a favicon package from a single image are useful.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="https://imgtask.com/favicon-generator" rel="noopener noreferrer"&gt;ImgTask's Favicon Generator&lt;/a&gt; takes one image and generates a ZIP containing a multi-size &lt;code&gt;favicon.ico&lt;/code&gt;, small PNG favicons, and an Apple touch icon.&lt;/p&gt;

&lt;p&gt;The conversion runs in the browser, without uploading the logo to a server for processing.&lt;/p&gt;

&lt;p&gt;It's a convenient option when you already have a square logo and just need the correct files for deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why isn't my new favicon showing up?
&lt;/h2&gt;

&lt;p&gt;This is another common problem.&lt;/p&gt;

&lt;p&gt;You replace the favicon, refresh the website, and the old icon is still there.&lt;/p&gt;

&lt;p&gt;Sometimes the issue isn't your HTML.&lt;/p&gt;

&lt;p&gt;Browsers can cache favicon files aggressively.&lt;/p&gt;

&lt;p&gt;Before changing your entire favicon configuration, check a few things.&lt;/p&gt;

&lt;p&gt;First, try opening the favicon file directly in the browser.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com/favicon.ico&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Make sure it returns the icon you expect.&lt;/p&gt;

&lt;p&gt;Then check the browser's developer tools to confirm the asset is loading successfully.&lt;/p&gt;

&lt;p&gt;You can also try a fresh browser profile or a private browsing window.&lt;/p&gt;

&lt;p&gt;If caching continues to cause problems, changing the asset filename or versioning its URL can help.&lt;/p&gt;

&lt;p&gt;For example:&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;link&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/favicon.ico?v=2"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on your hosting or CDN configuration, you may also need to invalidate cached files.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few design tips
&lt;/h2&gt;

&lt;p&gt;When preparing your favicon, keep these things in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with a square image.&lt;/li&gt;
&lt;li&gt;Use a simple, recognizable symbol.&lt;/li&gt;
&lt;li&gt;Avoid tiny text and complicated illustrations.&lt;/li&gt;
&lt;li&gt;Check how the icon looks against light and dark browser themes.&lt;/li&gt;
&lt;li&gt;Test it at 16 × 16 pixels, not just at its original resolution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point is important.&lt;/p&gt;

&lt;p&gt;An icon that looks beautiful at 512 pixels can become unreadable when displayed at 16 pixels.&lt;/p&gt;

&lt;p&gt;Always inspect the final result at the actual size your users will see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Favicons aren't the most exciting part of building a website.&lt;/p&gt;

&lt;p&gt;Nobody is going to choose a website because its favicon is amazing.&lt;/p&gt;

&lt;p&gt;But missing or poorly designed favicons can make an otherwise polished project feel unfinished.&lt;/p&gt;

&lt;p&gt;And since creating a proper favicon set takes very little time, there's really no reason to skip it.&lt;/p&gt;

&lt;p&gt;The next time you're preparing a website for launch, add the favicon check to your deployment checklist.&lt;/p&gt;

&lt;p&gt;What's the most commonly forgotten small detail in your web development projects?&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>web</category>
      <category>webdev</category>
    </item>
    <item>
      <title>JPEG vs WebP: What Developers Should Know Before Converting Website Images</title>
      <dc:creator>Christopher H. Dutra</dc:creator>
      <pubDate>Fri, 23 Oct 2026 06:46:45 +0000</pubDate>
      <link>https://dev.to/christopher-dutra/jpeg-vs-webp-what-developers-should-know-before-converting-website-images-11jo</link>
      <guid>https://dev.to/christopher-dutra/jpeg-vs-webp-what-developers-should-know-before-converting-website-images-11jo</guid>
      <description>&lt;p&gt;When building websites, we spend plenty of time choosing frameworks, optimizing JavaScript, and improving database queries.&lt;/p&gt;

&lt;p&gt;But there's another decision that can affect website performance: the image format.&lt;/p&gt;

&lt;p&gt;JPEG has been around for decades, and it still works well. However, newer formats such as WebP give developers more options when balancing file size and visual quality.&lt;/p&gt;

&lt;p&gt;So should we convert every JPEG image to WebP?&lt;/p&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;Let's explore when it makes sense and when it doesn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why JPEG is still everywhere
&lt;/h2&gt;

&lt;p&gt;JPEG is one of the most widely supported image formats.&lt;/p&gt;

&lt;p&gt;It works across browsers, operating systems, image editors, and countless older applications.&lt;/p&gt;

&lt;p&gt;For photographs, JPEG remains a perfectly reasonable choice.&lt;/p&gt;

&lt;p&gt;But JPEG compression has limitations.&lt;/p&gt;

&lt;p&gt;At aggressive compression settings, images can develop noticeable artifacts, particularly around text, edges, and detailed areas.&lt;/p&gt;

&lt;p&gt;Modern formats offer different compression techniques that may achieve better results.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes WebP different?
&lt;/h2&gt;

&lt;p&gt;WebP is an image format developed by Google.&lt;/p&gt;

&lt;p&gt;It supports lossy and lossless compression, along with transparency and animation.&lt;/p&gt;

&lt;p&gt;One of its biggest advantages is that photographic images can often be stored in smaller files than equivalent-looking JPEGs.&lt;/p&gt;

&lt;p&gt;For example, you might have a JPEG photograph that's several hundred kilobytes.&lt;/p&gt;

&lt;p&gt;After converting it to WebP, the result may become noticeably smaller while still looking similar.&lt;/p&gt;

&lt;p&gt;However, this isn't guaranteed.&lt;/p&gt;

&lt;p&gt;The savings depend on the image content, original compression, and conversion settings.&lt;/p&gt;

&lt;p&gt;An already optimized JPEG might not benefit much from conversion.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does this affect actual website performance?
&lt;/h2&gt;

&lt;p&gt;Suppose you're building an e-commerce product page.&lt;/p&gt;

&lt;p&gt;The page contains twelve product photographs.&lt;/p&gt;

&lt;p&gt;If each image is unnecessarily large, the total image payload can quickly become significant.&lt;/p&gt;

&lt;p&gt;Reducing the weight of those assets means fewer bytes need to travel over the network.&lt;/p&gt;

&lt;p&gt;That can help with loading performance, particularly on slower connections.&lt;/p&gt;

&lt;p&gt;But file size isn't the only performance factor. Image dimensions, network conditions, decoding time, caching, and loading priority matter too.&lt;/p&gt;

&lt;p&gt;WebP is useful, but it's not a substitute for a complete optimization strategy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serving WebP with a JPEG fallback
&lt;/h2&gt;

&lt;p&gt;Modern browsers support WebP, but keeping a JPEG fallback can still make sense for legacy environments and certain workflows.&lt;/p&gt;

&lt;p&gt;The HTML &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; element allows you to provide alternative formats:&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;picture&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;source&lt;/span&gt;
    &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"/images/product.webp"&lt;/span&gt;
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/webp"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&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;"/images/product.jpg"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Wireless keyboard on a desk"&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;"600"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/picture&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A browser that supports WebP can use the WebP source.&lt;/p&gt;

&lt;p&gt;If WebP isn't supported, the JPEG image remains available.&lt;/p&gt;

&lt;p&gt;This is particularly useful when compatibility with older browsing environments is a requirement.&lt;/p&gt;

&lt;p&gt;For modern applications without those compatibility requirements, using WebP directly may be sufficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Converting existing JPEG assets
&lt;/h2&gt;

&lt;p&gt;You don't always need to change your application's code to prepare WebP files.&lt;/p&gt;

&lt;p&gt;For a Node.js build pipeline, the Sharp library is one option.&lt;/p&gt;

&lt;p&gt;Here's a small example:&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;product.jpg&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="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;80&lt;/span&gt; &lt;span class="p"&gt;})&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;product.webp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Image converted.&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;p&gt;This reads an image, converts it to WebP with a specified quality setting, and writes the output file.&lt;/p&gt;

&lt;p&gt;For a larger project, you could extend this to process an entire assets directory.&lt;/p&gt;

&lt;p&gt;But sometimes you just want to convert five or ten images manually.&lt;/p&gt;

&lt;p&gt;In those situations, I like the simplicity of a browser-based converter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://imgtask.com/jpg-to-webp" rel="noopener noreferrer"&gt;ImgTask's JPG to WebP Converter&lt;/a&gt; allows you to select JPEG images, adjust the output quality, and download the converted files.&lt;/p&gt;

&lt;p&gt;It also supports multiple image uploads, and the conversion happens locally in the browser rather than uploading the files for server-side processing.&lt;/p&gt;

&lt;p&gt;It's a convenient alternative when setting up a full image-processing pipeline would be unnecessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be careful with repeated conversions
&lt;/h2&gt;

&lt;p&gt;Here's something worth remembering.&lt;/p&gt;

&lt;p&gt;JPEG uses lossy compression.&lt;/p&gt;

&lt;p&gt;If you convert a JPEG to lossy WebP, you're compressing data that has already been compressed.&lt;/p&gt;

&lt;p&gt;That means conversion cannot magically recover details lost in the original JPEG.&lt;/p&gt;

&lt;p&gt;Repeated conversions can introduce additional degradation.&lt;/p&gt;

&lt;p&gt;Whenever possible, generate your final image formats from a high-quality original.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Original high-quality image
          |
          |
   ----------------
   |              |
 JPEG output    WebP output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is generally better than:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Original → JPEG → WebP → JPEG → WebP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second workflow introduces unnecessary recompression.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you keep JPEG?
&lt;/h2&gt;

&lt;p&gt;Despite WebP's advantages, JPEG still makes sense in several situations.&lt;/p&gt;

&lt;p&gt;Some external platforms and older applications expect JPEG uploads.&lt;/p&gt;

&lt;p&gt;Printing workflows may require specific image formats or color-management handling.&lt;/p&gt;

&lt;p&gt;You might also be working with an existing image pipeline that already generates well-optimized JPEGs.&lt;/p&gt;

&lt;p&gt;And sometimes the actual file-size difference is so small that conversion provides little practical benefit.&lt;/p&gt;

&lt;p&gt;Choose a format based on your project's needs rather than simply choosing the newest option.&lt;/p&gt;

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

&lt;p&gt;For most modern websites, I'd suggest this approach:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep a high-quality original image.&lt;/li&gt;
&lt;li&gt;Resize it to the dimensions your interface needs.&lt;/li&gt;
&lt;li&gt;Generate a WebP version.&lt;/li&gt;
&lt;li&gt;Compare quality and file size against JPEG.&lt;/li&gt;
&lt;li&gt;Test the image in its actual page layout.&lt;/li&gt;
&lt;li&gt;Keep a JPEG alternative where compatibility matters.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You don't have to convert everything at once.&lt;/p&gt;

&lt;p&gt;Start with the largest images on your most important pages and measure the results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;WebP isn't a magic solution for slow websites, but it is a useful tool.&lt;/p&gt;

&lt;p&gt;When combined with sensible dimensions, responsive images, and good loading strategies, it can help make pages lighter.&lt;/p&gt;

&lt;p&gt;The goal isn't to use the most modern image format everywhere.&lt;/p&gt;

&lt;p&gt;The goal is to deliver images that look good without transferring unnecessary data.&lt;/p&gt;

&lt;p&gt;That's a much better way to think about image optimization.&lt;/p&gt;

&lt;p&gt;Are you using WebP, AVIF, or traditional JPEGs in your current projects?&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>performance</category>
      <category>web</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why Image Optimization Should Be Part of Every Developer's Workflow</title>
      <dc:creator>Christopher H. Dutra</dc:creator>
      <pubDate>Fri, 23 Oct 2026 06:43:49 +0000</pubDate>
      <link>https://dev.to/christopher-dutra/why-image-optimization-should-be-part-of-every-developers-workflow-3iip</link>
      <guid>https://dev.to/christopher-dutra/why-image-optimization-should-be-part-of-every-developers-workflow-3iip</guid>
      <description>&lt;h1&gt;
  
  
  Why Image Optimization Should Be Part of Every Developer's Workflow
&lt;/h1&gt;

&lt;p&gt;You can build a beautiful website, write clean code, use a modern framework, and still end up with a painfully slow page.&lt;/p&gt;

&lt;p&gt;Sometimes the problem isn't JavaScript, your database, or your hosting provider. It's a handful of images that nobody thought to optimize.&lt;/p&gt;

&lt;p&gt;Images are one of those things that seem harmless during development. You download a photo, add it to your project, and move on. Everything looks fine locally.&lt;/p&gt;

&lt;p&gt;Then you check the website on a slower mobile connection, and suddenly those beautiful images become a performance problem.&lt;/p&gt;

&lt;p&gt;Let's talk about a few practical ways to avoid that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with unoptimized images
&lt;/h2&gt;

&lt;p&gt;Imagine you're building a landing page for a business.&lt;/p&gt;

&lt;p&gt;You have a hero image, three service images, a few customer photos, and some decorative graphics.&lt;/p&gt;

&lt;p&gt;Individually, none of them seems particularly large. But imagine each photo is 2–4 MB.&lt;/p&gt;

&lt;p&gt;Now a visitor might download more than 10 MB of images just to view one page.&lt;/p&gt;

&lt;p&gt;That's a lot of unnecessary data, particularly for someone on a mobile connection.&lt;/p&gt;

&lt;p&gt;The interesting part is that you can often reduce image file sizes significantly without making them look noticeably worse.&lt;/p&gt;

&lt;p&gt;And you don't necessarily need an expensive image editor to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compression and resizing are different things
&lt;/h2&gt;

&lt;p&gt;These two concepts are often confused.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Image compression&lt;/strong&gt; reduces the number of bytes required to store an image. Depending on the format, this might involve removing redundant data or discarding some visual detail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Image resizing&lt;/strong&gt; changes the image's pixel dimensions.&lt;/p&gt;

&lt;p&gt;For example, suppose you have a 4000 × 3000 pixel photograph.&lt;/p&gt;

&lt;p&gt;You can compress that photograph while keeping its original dimensions.&lt;/p&gt;

&lt;p&gt;But if your website displays it at only 800 pixels wide, you should probably resize it too.&lt;/p&gt;

&lt;p&gt;A practical workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Determine the dimensions your interface actually needs.&lt;/li&gt;
&lt;li&gt;Resize the source image if necessary.&lt;/li&gt;
&lt;li&gt;Choose an appropriate output format.&lt;/li&gt;
&lt;li&gt;Compress the image.&lt;/li&gt;
&lt;li&gt;Compare its visual quality with the original.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's a simple process, but it can make a meaningful difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the right image format
&lt;/h2&gt;

&lt;p&gt;Not every image should be treated the same way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JPEG&lt;/strong&gt; remains useful for photographs, especially when compatibility matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PNG&lt;/strong&gt; is excellent for graphics that need transparency or lossless detail, such as certain screenshots and logos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WebP&lt;/strong&gt; is a good option for modern websites because it often produces smaller files than JPEG or PNG at comparable visual quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AVIF&lt;/strong&gt; can deliver excellent compression too, although encoding support, performance, and compatibility with your particular workflow should be considered.&lt;/p&gt;

&lt;p&gt;There's no universal winner.&lt;/p&gt;

&lt;p&gt;For a website with many photographic images, I'd usually start by testing WebP. For simple graphics where exact pixels matter, PNG may still be preferable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let the browser do less work
&lt;/h2&gt;

&lt;p&gt;Optimizing image files is only one part of the process.&lt;/p&gt;

&lt;p&gt;Consider this HTML:&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;"/images/product.webp"&lt;/span&gt;
  &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Product displayed on a wooden desk"&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;"600"&lt;/span&gt;
  &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
  &lt;span class="na"&gt;decoding=&lt;/span&gt;&lt;span class="s"&gt;"async"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few small details matter here.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; attributes help the browser reserve layout space, reducing unexpected movement as the image loads.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;loading="lazy"&lt;/code&gt; delays loading images that aren't immediately needed.&lt;/p&gt;

&lt;p&gt;And &lt;code&gt;decoding="async"&lt;/code&gt; allows image decoding without necessarily blocking other rendering work.&lt;/p&gt;

&lt;p&gt;One important exception: don't automatically lazy-load your main hero image or Largest Contentful Paint (LCP) image. That image usually needs to load early.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small tool that makes image preparation easier
&lt;/h2&gt;

&lt;p&gt;When working on websites, it's useful to have an easy way to prepare images without opening a full design application.&lt;/p&gt;

&lt;p&gt;That's one of the reasons we built &lt;a href="https://imgtask.com/compress-image" rel="noopener noreferrer"&gt;ImgTask's Image Compressor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It supports multiple image formats, lets you adjust compression quality, and offers an optional target file size.&lt;/p&gt;

&lt;p&gt;You can also compare the original and compressed versions before downloading.&lt;/p&gt;

&lt;p&gt;One feature I particularly appreciate is that image compression happens in the browser. The images aren't uploaded to ImgTask's server for processing.&lt;/p&gt;

&lt;p&gt;It's useful when preparing client website assets or handling images you'd prefer to keep on your device.&lt;/p&gt;

&lt;p&gt;Of course, for large automated production pipelines, tools such as Sharp or build-time image processing are more appropriate.&lt;/p&gt;

&lt;p&gt;But for manually preparing a handful of assets, a browser-based tool is convenient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't forget responsive images
&lt;/h2&gt;

&lt;p&gt;Another common problem is serving the same large image to every device.&lt;/p&gt;

&lt;p&gt;A phone with a narrow screen usually doesn't need the same file dimensions as a large desktop monitor.&lt;/p&gt;

&lt;p&gt;HTML provides a straightforward solution:&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;"/images/banner-800.webp"&lt;/span&gt;
  &lt;span class="na"&gt;srcset=&lt;/span&gt;&lt;span class="s"&gt;"
    /images/banner-400.webp 400w,
    /images/banner-800.webp 800w,
    /images/banner-1200.webp 1200w
  "&lt;/span&gt;
  &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"(max-width: 600px) 100vw, 800px"&lt;/span&gt;
  &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Website banner"&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="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;srcset&lt;/code&gt; and &lt;code&gt;sizes&lt;/code&gt;, the browser can select a suitable resource based on the layout and device.&lt;/p&gt;

&lt;p&gt;Just remember that all the referenced image sizes need to exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  My practical image optimization checklist
&lt;/h2&gt;

&lt;p&gt;Before publishing a website, I think it's worth checking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are any images significantly larger than their displayed dimensions?&lt;/li&gt;
&lt;li&gt;Have photographic assets been compressed appropriately?&lt;/li&gt;
&lt;li&gt;Would WebP or AVIF make sense for the project?&lt;/li&gt;
&lt;li&gt;Do images have meaningful alternative text?&lt;/li&gt;
&lt;li&gt;Are width and height attributes provided?&lt;/li&gt;
&lt;li&gt;Are below-the-fold images lazy-loaded?&lt;/li&gt;
&lt;li&gt;Have important images been tested on slower connections?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't complicated optimizations. They're small habits that add up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;It's easy to get excited about frameworks, new libraries, and complicated performance techniques.&lt;/p&gt;

&lt;p&gt;But sometimes the most useful improvement is much simpler.&lt;/p&gt;

&lt;p&gt;Take a look at the images your website is sending to visitors.&lt;/p&gt;

&lt;p&gt;Resize what doesn't need to be huge, compress what can be smaller, and serve formats appropriate for the situation.&lt;/p&gt;

&lt;p&gt;Your users shouldn't have to download several megabytes of unnecessary data just to read a page.&lt;/p&gt;

&lt;p&gt;And if you want a quick way to prepare assets manually, the &lt;a href="https://imgtask.com/compress-image" rel="noopener noreferrer"&gt;ImgTask Image Compressor&lt;/a&gt; is one option.&lt;/p&gt;

&lt;p&gt;What's your preferred approach to image optimization? Do you handle it during development, at build time, or through an image CDN?&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>performance</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
