<?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: Ethan Brooks</title>
    <description>The latest articles on DEV Community by Ethan Brooks (@eathan_brooks).</description>
    <link>https://dev.to/eathan_brooks</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%2F4162977%2Ffbfd9933-f790-4db4-9ec6-9953678fa177.jpg</url>
      <title>DEV Community: Ethan Brooks</title>
      <link>https://dev.to/eathan_brooks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eathan_brooks"/>
    <language>en</language>
    <item>
      <title>Treat image prompts like functions: what 1,446 shared prompts say about templates</title>
      <dc:creator>Ethan Brooks</dc:creator>
      <pubDate>Mon, 05 Oct 2026 10:07:42 +0000</pubDate>
      <link>https://dev.to/eathan_brooks/treat-image-prompts-like-functions-what-1446-shared-prompts-say-about-templates-4d7d</link>
      <guid>https://dev.to/eathan_brooks/treat-image-prompts-like-functions-what-1446-shared-prompts-say-about-templates-4d7d</guid>
      <description>&lt;p&gt;Most people write an AI image prompt the way they'd write a search query: once, for one result, then throw it away.&lt;/p&gt;

&lt;p&gt;The prompts that get shared and reused look different. We went through 1,446 popular image prompts in an openly licensed dataset, and a lot of them are written more like code than like sentences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two patterns that stood out
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;About 22% are templates.&lt;/strong&gt; 323 of the 1,446 prompts contain at least one placeholder in square brackets, such as &lt;code&gt;[OBJECT]&lt;/code&gt;, &lt;code&gt;[COLOR]&lt;/code&gt;, &lt;code&gt;[COUNTRY]&lt;/code&gt; or &lt;code&gt;[BRAND NAME]&lt;/code&gt;. The author wrote the structure once and left slots for the parts that change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About 21% are written as JSON.&lt;/strong&gt; 299 prompts are structured objects with keys for things like the scene, lighting and camera, rather than a paragraph.&lt;/p&gt;

&lt;p&gt;They're also long. The median prompt is about 1,000 characters. These aren't one-liners.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a template beats a one-off prompt
&lt;/h2&gt;

&lt;p&gt;The top-ranked prompt in the dataset, shared by TechieSA, starts like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a technical infographic of [OBJECT] with a 45-degree isometric 3D perspective…&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Everything after that line, the angle, the annotation style, the colour-coded arrows, stays fixed. Only &lt;code&gt;[OBJECT]&lt;/code&gt; changes. Swap in a phone, a camera or a coffee machine and you get a consistent series, not a pile of unrelated images.&lt;/p&gt;

&lt;p&gt;That's the same reason we write functions instead of copying code: one definition, many calls, and a fix in one place applies everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning your own prompt into a template
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Write it once for a real case&lt;/strong&gt; and keep iterating until you like the result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circle what would change&lt;/strong&gt; between uses: the subject, a colour, a place, a brand. Those become placeholders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name the slots clearly.&lt;/strong&gt; &lt;code&gt;[PRODUCT]&lt;/code&gt; is better than &lt;code&gt;[X]&lt;/code&gt;, because future you won't remember what X was.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freeze everything else.&lt;/strong&gt; The style, the lighting and the camera words are what make the series consistent, so resist editing them per image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fill the slots in code&lt;/strong&gt; if you're generating many images:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;infographic_prompt.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mechanical keyboard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;film camera&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;espresso machine&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[OBJECT]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# your image API call here
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When JSON helps, and when it doesn't
&lt;/h2&gt;

&lt;p&gt;JSON prompts make each part of the image an explicit field, which is handy when a script fills them in or when you want to change one property and keep the rest. Models still read them as text, though, so there's nothing magic about the braces. If a plain paragraph with clear placeholders does the job, it's easier to read and edit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the numbers come from
&lt;/h2&gt;

&lt;p&gt;The counts are from the nanobanana-trending-prompts dataset, published by MeiGen.ai under CC BY 4.0. The prompts belong to the creators who shared them.&lt;/p&gt;

&lt;p&gt;Prompt House is a free gallery built on that dataset, with each prompt shown beside the image it produced and credited to its creator. If you want to see templates like these in action, browse the &lt;a href="https://prompthouse.studio/trending-ai-prompts" rel="noopener noreferrer"&gt;trending AI image prompts&lt;/a&gt; and look for the square brackets.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Written by the Prompt House team. Prompt House is a free AI prompt gallery made by APPDOOK. The counts above were made by searching the dataset's prompt text in October 2026.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>promptengineering</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Four green buttons and only one is real: how to spot a dark-pattern download site</title>
      <dc:creator>Ethan Brooks</dc:creator>
      <pubDate>Mon, 05 Oct 2026 09:04:18 +0000</pubDate>
      <link>https://dev.to/eathan_brooks/four-green-buttons-and-only-one-is-real-how-to-spot-a-dark-pattern-download-site-h1m</link>
      <guid>https://dev.to/eathan_brooks/four-green-buttons-and-only-one-is-real-how-to-spot-a-dark-pattern-download-site-h1m</guid>
      <description>&lt;p&gt;You paste a link into a free download site, and the page suddenly fills with big green buttons. Download. Download Now. Start Download. Click one and a new tab opens, then another, and somewhere along the way your browser asks to show you notifications.&lt;/p&gt;

&lt;p&gt;Most of those buttons are ads. Some lead somewhere much worse than an ad. Here's how to tell the difference, and what anyone building a free tool can learn from it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five warning signs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. More than one "Download" button.&lt;/strong&gt; Ads are often designed to look exactly like the site's own button. The real one usually appears only after you've chosen a format, right next to what you pasted. If several identical buttons appear at once, assume most of them aren't the site's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A new tab opens wherever you click.&lt;/strong&gt; Some sites open an advert or a chain of redirects in a new tab on your first click, sometimes even a click on empty space. A tool that works honestly doesn't need to take you anywhere else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. "Click Allow to continue."&lt;/strong&gt; No download needs permission to send you notifications. That prompt is a way to push spam and fake alerts to your device later. Click Block, every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The file isn't what you asked for.&lt;/strong&gt; You wanted a video or an audio file, and you got a file ending in &lt;code&gt;.exe&lt;/code&gt;, &lt;code&gt;.apk&lt;/code&gt;, &lt;code&gt;.dmg&lt;/code&gt; or an unexpected &lt;code&gt;.zip&lt;/code&gt;. Don't open it. Delete it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. "Install our app or extension for HD", or "your device is infected".&lt;/strong&gt; A web tool that genuinely works in the browser doesn't need you to install anything, and a website cannot scan your device for viruses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three habits that keep you safe
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hover before you click.&lt;/strong&gt; On a computer, the link's real destination shows in the corner of the browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch the download panel.&lt;/strong&gt; Check the file name and type before you open anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leave at the first warning sign.&lt;/strong&gt; There's always another tool. There isn't always an easy fix for malware.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  If you're building a free tool
&lt;/h2&gt;

&lt;p&gt;Most free tools are paid for by ads, and that's fair. But there's a big difference between showing ads and disguising them. A few rules worth following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep ads in a clearly separate space, never styled like your own controls.&lt;/li&gt;
&lt;li&gt;Give the page one obvious primary action.&lt;/li&gt;
&lt;li&gt;Never open a new tab on a click the user didn't mean for that.&lt;/li&gt;
&lt;li&gt;Never ask for notification permission as a condition of using the tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users notice. A tool that respects these rules is one people come back to, and recommend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where we stand
&lt;/h2&gt;

&lt;p&gt;We built Kino around those rules: no fake download buttons, no redirect chains, no account and nothing to install. It's ad-supported, with the ads kept in their own space, and downloaded files are deleted automatically after a short time. You can try it at &lt;a href="https://kinosave.social/" rel="noopener noreferrer"&gt;kinosave.social&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Kino is meant for saving content you have the right to keep, such as your own uploads or openly licensed video.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Written by the Kino team. Kino is a free video downloader made by APPDOOK.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ux</category>
      <category>security</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Local news without a location prompt: how we pick a reader's edition in Next.js</title>
      <dc:creator>Ethan Brooks</dc:creator>
      <pubDate>Mon, 05 Oct 2026 08:23:06 +0000</pubDate>
      <link>https://dev.to/eathan_brooks/local-news-without-a-location-prompt-how-we-pick-a-readers-edition-in-nextjs-578</link>
      <guid>https://dev.to/eathan_brooks/local-news-without-a-location-prompt-how-we-pick-a-readers-edition-in-nextjs-578</guid>
      <description>&lt;p&gt;A news site with editions for different countries has to answer one question on every request: which edition should this reader see?&lt;/p&gt;

&lt;p&gt;The easy answer is the browser's location prompt. We decided never to show it. Here's the order of fallbacks we use instead, and the small details that turned out to matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  The resolution order
&lt;/h2&gt;

&lt;p&gt;The edition is decided in Next.js middleware (the proxy), before any page renders. It takes the first of these that exists:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The reader's own choice.&lt;/strong&gt; If they've picked an edition in the switcher, a cookie remembers it and it wins over everything else.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The hosting network's geo headers.&lt;/strong&gt; The host already derives an approximate country, region and city from the IP address. We read those.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The device's time zone.&lt;/strong&gt; When there are no geo headers, the browser's IANA time zone is a surprisingly good hint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A default.&lt;/strong&gt; If all else fails, the U.S. edition.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nothing in this list needs a permission dialog. All of it is information the request already carries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detail 1: validate the geo header, even though your host sent it
&lt;/h2&gt;

&lt;p&gt;Geo headers aren't always a clean two-letter country code. Cloudflare uses &lt;code&gt;XX&lt;/code&gt; for "unknown" and codes with digits for things like Tor. If you pass those straight through, you end up looking for the "XX edition".&lt;/p&gt;

&lt;p&gt;We accept a country only if it matches &lt;code&gt;^[A-Z]{2}$&lt;/code&gt; and isn't &lt;code&gt;XX&lt;/code&gt;. Everything else falls through to the next step in the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detail 2: skip time zones that span several countries
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Asia/Kolkata&lt;/code&gt; points to India. &lt;code&gt;Europe/London&lt;/code&gt; points to the U.K. Some zones are shared by several countries, though, and guessing among them is worse than not guessing.&lt;/p&gt;

&lt;p&gt;Our time-zone table simply leaves those out. Where a zone does pin down a place, like &lt;code&gt;Australia/Perth&lt;/code&gt;, it fills in the state and city as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detail 3: overwrite the headers your pages trust
&lt;/h2&gt;

&lt;p&gt;The middleware passes the result to pages as request headers such as &lt;code&gt;x-user-country&lt;/code&gt;. It always sets them itself and deletes any incoming copies first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requestHeaders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;requestHeaders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;COUNTRY_HEADER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;requestHeaders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;REGION_HEADER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;requestHeaders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CITY_HEADER&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise a client could send its own &lt;code&gt;x-user-country&lt;/code&gt; and the page would believe it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detail 4: only show state and city for the reader's own country
&lt;/h2&gt;

&lt;p&gt;If a reader in Ohio switches to the U.K. edition, they shouldn't see "local news for Ohio" mixed into British headlines. Region and city are only passed on when the edition being served is the reader's detected country.&lt;/p&gt;

&lt;h2&gt;
  
  
  Detail 5: don't set cookies on pages that should be cached
&lt;/h2&gt;

&lt;p&gt;The middleware remembers the detected edition in a short-lived cookie. At first it set that cookie on every response, including article pages. But a caching layer like nginx or Cloudflare won't store a response that sets a cookie, so the pages most readers arrive on from search could never be cached.&lt;/p&gt;

&lt;p&gt;Article pages are the same for every reader, so they don't need the cookie at all. Now the middleware returns early for &lt;code&gt;/news/&lt;/code&gt; paths, and the cookie is set on the first edition-dependent page the reader opens instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we store
&lt;/h2&gt;

&lt;p&gt;No precise location, ever. The cookies hold the chosen or detected country code, how it was detected, and the time zone name. A VPN can put a reader in the wrong edition, which is exactly why the manual choice comes first.&lt;/p&gt;

&lt;p&gt;This is how editions work on &lt;a href="https://yuphora.com/about" rel="noopener noreferrer"&gt;Yuphora&lt;/a&gt;, our free news site with editions for 13 countries. The About page lists every source we draw on and how each is licensed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Written by the Yuphora News team. Yuphora is a free, ad-supported news site published by APPDOOK.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>privacy</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Should you require the new iOS? A five-question checklist before you touch the deployment target</title>
      <dc:creator>Ethan Brooks</dc:creator>
      <pubDate>Mon, 05 Oct 2026 07:11:22 +0000</pubDate>
      <link>https://dev.to/eathan_brooks/should-you-require-the-new-ios-a-five-question-checklist-before-you-touch-the-deployment-target-21lo</link>
      <guid>https://dev.to/eathan_brooks/should-you-require-the-new-ios-a-five-question-checklist-before-you-touch-the-deployment-target-21lo</guid>
      <description>&lt;p&gt;Every September someone on the team asks the same thing: now that the new iOS is out, can we just require it?&lt;/p&gt;

&lt;p&gt;It sounds like housekeeping. It isn't. Raising your minimum OS is one of the few decisions that can quietly remove paying users from your app, and it's usually made in a five-minute conversation. Here is the checklist we use at APPDOOK to slow that conversation down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Can every affected user actually update?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the question people skip, because they picture the user who just hasn't tapped Update yet. That user exists, but they're not the problem.&lt;/p&gt;

&lt;p&gt;The problem is hardware. iOS 27, released on 14 September, runs on the iPhone 15 Pro and Pro Max, the iPhone 16 line and later, iPhone Air and iPhone Duo. Every non-Pro iPhone before the 16 is left out. That is a cut into phones people bought in the last two years.&lt;/p&gt;

&lt;p&gt;For those users, a higher deployment target isn't a nudge to update. It's a request to buy a new phone. Most won't, and they won't email you about it either. They'll just stop getting updates, or stop finding you in the App Store.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Is the API you want load-bearing, or just convenient?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The reason given for raising the target is almost always one specific API. Ask honestly which kind it is.&lt;/p&gt;

&lt;p&gt;If it's convenient, an availability check costs a few lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;#available&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iOS&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;useNewAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;useExistingPath&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it's load-bearing, you need a designed fallback anyway. A feature that silently disappears on older devices doesn't save work. It turns into support tickets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Are you confusing "build with the new SDK" and "require the new OS"?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are two separate decisions, and they get bundled together all the time.&lt;/p&gt;

&lt;p&gt;Building against the newest SDK is cheap and you should do it immediately. You get the new APIs, and you see deprecation warnings early. Requiring the newest OS is expensive, for all the reasons above. You can do the first without the second.&lt;/p&gt;

&lt;p&gt;The short version: build against the newest SDK, and require the oldest OS you can live with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Do you have your own numbers?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Industry averages for OS adoption are interesting, but they're not your users. Before the conversation, pull the OS version split from your own analytics or App Store Connect.&lt;/p&gt;

&lt;p&gt;Every argument in this checklist gets stronger, or weaker, once you can say "this would cut off X% of our active users" instead of "probably not many people".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Is this one of the real exceptions?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are cases where requiring the newest OS is fine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a brand-new app with no installed base to leave behind&lt;/li&gt;
&lt;li&gt;an internal tool on managed devices, where you know exactly which hardware is in the fleet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are real. They're also much rarer than the number of times the question gets asked.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do instead
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep the deployment target where it is, and adopt new APIs behind availability checks.&lt;/li&gt;
&lt;li&gt;Build and test against the new SDK now.&lt;/li&gt;
&lt;li&gt;Bring your own OS version numbers to the discussion.&lt;/li&gt;
&lt;li&gt;Put the question back on the calendar for about a year from now, once the current hardware generation has spread.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last step matters. "Not now" is a much easier answer to give when it comes with a date for "later".&lt;/p&gt;

&lt;p&gt;We went through this year's device list in more detail, including why this cut is different from most years, in &lt;a href="https://appdook.com/news/ios-27-minimum-deployment-target-decision" rel="noopener noreferrer"&gt;APPDOOK's notes on raising the deployment target&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Written by the APPDOOK team, a small product studio in Surat, India. If your team has a different rule of thumb for this decision, we'd like to hear it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>mobile</category>
      <category>productmanagement</category>
    </item>
  </channel>
</rss>
