<?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: Oleh Veheria</title>
    <description>The latest articles on DEV Community by Oleh Veheria (@5uper0).</description>
    <link>https://dev.to/5uper0</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%2F4027271%2Fb47d7f3a-d282-461e-98ec-c9801a73c150.png</url>
      <title>DEV Community: Oleh Veheria</title>
      <link>https://dev.to/5uper0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/5uper0"/>
    <language>en</language>
    <item>
      <title>Stack Overflow Mobile Questions Fell 95 to 99.5% Since 2022. The Whole Site Fell 99.1%</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Mon, 02 Nov 2026 08:14:30 +0000</pubDate>
      <link>https://dev.to/5uper0/stack-overflow-mobile-questions-fell-95-to-995-since-2022-the-whole-site-fell-991-3jeo</link>
      <guid>https://dev.to/5uper0/stack-overflow-mobile-questions-fell-95-to-995-since-2022-the-whole-site-fell-991-3jeo</guid>
      <description>&lt;p&gt;The &lt;a href="https://veheria.tech/blog/npm-downloads-react-native-expo-capacitor-46-months/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=so-mobile" rel="noopener noreferrer"&gt;earlier posts in this series&lt;/a&gt; used Hacker News and npm. This one counts questions. Stack Overflow has a public API that returns the number of new questions for any tag in any date range, so I pulled quarterly counts for six mobile tags, &lt;code&gt;swiftui&lt;/code&gt;, &lt;code&gt;uikit&lt;/code&gt;, &lt;code&gt;jetpack-compose&lt;/code&gt;, &lt;code&gt;kotlin-multiplatform&lt;/code&gt;, &lt;code&gt;react-native&lt;/code&gt; and &lt;code&gt;flutter&lt;/code&gt;, plus the site total as a control, from Q1 2022 to Q3 2026.&lt;/p&gt;

&lt;p&gt;Every tag fell by 95% or more. So did the site: from 356,065 new questions in Q1 2022 to 3,160 in Q3 2026, a drop of 99.1%. The mobile tags did not escape it, so question volume stopped working as a popularity signal. What is left is the mix between them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5p2yjzv564a0wemi49x5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5p2yjzv564a0wemi49x5.png" alt="Line chart: new Stack Overflow questions per quarter indexed to Q1 2022 = 100 on a log scale. By Q3 2026 all of Stack Overflow is at 0.9, native mobile tags at 2.2, React Native plus Flutter at 0.5." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the counts say
&lt;/h2&gt;

&lt;p&gt;New questions per quarter, from the Stack Exchange API. "Native" is &lt;code&gt;swiftui&lt;/code&gt;, &lt;code&gt;uikit&lt;/code&gt;, &lt;code&gt;jetpack-compose&lt;/code&gt; and &lt;code&gt;kotlin-multiplatform&lt;/code&gt; added together. "Cross" is &lt;code&gt;react-native&lt;/code&gt; and &lt;code&gt;flutter&lt;/code&gt; added together. A question with two of these tags counts twice in the sums.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quarter&lt;/th&gt;
&lt;th&gt;All SO&lt;/th&gt;
&lt;th&gt;Native&lt;/th&gt;
&lt;th&gt;Cross&lt;/th&gt;
&lt;th&gt;Cross per native&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2022-Q1&lt;/td&gt;
&lt;td&gt;356,065&lt;/td&gt;
&lt;td&gt;3,482&lt;/td&gt;
&lt;td&gt;16,740&lt;/td&gt;
&lt;td&gt;4.81&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2023-Q1&lt;/td&gt;
&lt;td&gt;269,315&lt;/td&gt;
&lt;td&gt;3,308&lt;/td&gt;
&lt;td&gt;11,687&lt;/td&gt;
&lt;td&gt;3.53&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024-Q1&lt;/td&gt;
&lt;td&gt;138,199&lt;/td&gt;
&lt;td&gt;2,543&lt;/td&gt;
&lt;td&gt;5,737&lt;/td&gt;
&lt;td&gt;2.26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025-Q1&lt;/td&gt;
&lt;td&gt;48,755&lt;/td&gt;
&lt;td&gt;1,074&lt;/td&gt;
&lt;td&gt;1,984&lt;/td&gt;
&lt;td&gt;1.85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-Q1&lt;/td&gt;
&lt;td&gt;9,642&lt;/td&gt;
&lt;td&gt;226&lt;/td&gt;
&lt;td&gt;361&lt;/td&gt;
&lt;td&gt;1.60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-Q3&lt;/td&gt;
&lt;td&gt;3,160&lt;/td&gt;
&lt;td&gt;78&lt;/td&gt;
&lt;td&gt;84&lt;/td&gt;
&lt;td&gt;1.08&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Per tag, first and last quarter:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;2022-Q1&lt;/th&gt;
&lt;th&gt;2026-Q3&lt;/th&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;flutter&lt;/td&gt;
&lt;td&gt;11,998&lt;/td&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;td&gt;-99.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;react-native&lt;/td&gt;
&lt;td&gt;4,742&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;-99.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;swiftui&lt;/td&gt;
&lt;td&gt;2,195&lt;/td&gt;
&lt;td&gt;43&lt;/td&gt;
&lt;td&gt;-98.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;jetpack-compose&lt;/td&gt;
&lt;td&gt;898&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;-97.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uikit&lt;/td&gt;
&lt;td&gt;281&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;-97.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;kotlin-multiplatform&lt;/td&gt;
&lt;td&gt;108&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;-95.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three readings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The whole site collapsed, so absolute counts measure Stack Overflow.&lt;/strong&gt; The drop accelerated from 2023, with the steepest quarters in 2025 and 2026. I did not test why. A common explanation is that developers ask AI assistants first, but nothing in this data separates that from other causes, so I would not lean on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cross-platform tags fell faster than the native tags.&lt;/strong&gt; React Native and Flutter together lost 99.5%, the four native tags together lost 97.8%, the site lost 99.1%. In Q1 2022 there were 4.81 cross-platform questions per native question. In Q3 2026 there were 1.08, and the ratio went down in most quarters in between.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Share of the site shows it from the other side, on small counts.&lt;/strong&gt; The native tags were 0.98% of all new questions in Q1 2022 and 2.47% in Q3 2026, with a high of 2.75% in Q3 2025. React Native and Flutter together went from 4.70% to 2.66%, but that share stayed between 3.9% and 4.9% through 2025 and fell only in 2026 (3.74%, 2.73%, 2.66%), where the counts are small. The ratio above is the steadier signal.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does and does not say
&lt;/h2&gt;

&lt;p&gt;Fewer questions about a framework does not mean fewer people using it. Flutter lost the most volume partly because it had the most to lose: it was the biggest of the six tags by far. A framework that produces fewer questions per developer, because tooling or documentation got better, would also show a decline. The &lt;a href="https://veheria.tech/blog/hn-who-is-hiring-native-mobile-vs-ai-46-months/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=so-mobile" rel="noopener noreferrer"&gt;hiring counts&lt;/a&gt; and the &lt;a href="https://veheria.tech/blog/npm-downloads-react-native-expo-capacitor-46-months/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=so-mobile" rel="noopener noreferrer"&gt;npm installs&lt;/a&gt; measure other things and answer different questions, so none of the three settles which stack is winning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Counts are new questions with the tag at the time of the API call. Questions deleted later are not counted, so recent quarters may shrink in a later run as deletions catch up.&lt;/li&gt;
&lt;li&gt;The Q3 2026 counts are small (22 for &lt;code&gt;react-native&lt;/code&gt;, 5 for &lt;code&gt;kotlin-multiplatform&lt;/code&gt;). A shift of a few questions moves a share noticeably.&lt;/li&gt;
&lt;li&gt;Tags are chosen by the asker. Swift and Kotlin questions without a framework tag, and &lt;code&gt;ios&lt;/code&gt;, &lt;code&gt;android&lt;/code&gt; and &lt;code&gt;swift&lt;/code&gt; tags, are not in the six.&lt;/li&gt;
&lt;li&gt;Sums count a question once per matching tag, so the ratio is approximate.&lt;/li&gt;
&lt;li&gt;Stack Overflow is one source and its audience changed over the window.&lt;/li&gt;
&lt;li&gt;I ran the script twice and the two result sets were identical. Data retrieved 2026-11-01.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gzip&lt;/span&gt;

&lt;span class="n"&gt;TAGS&lt;/span&gt; &lt;span class="o"&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;swiftui&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;uikit&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;jetpack-compose&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;react-native&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;flutter&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;kotlin-multiplatform&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://api.stackexchange.com/2.3/questions?site=stackoverflow&amp;amp;filter=total&amp;amp;fromdate=%d&amp;amp;todate=%d&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="n"&gt;ts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tzinfo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;amp;tagged=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&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;Accept-Encoding&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;gzip&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&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="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gzip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decompress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;backoff&lt;/span&gt;&lt;span class="sh"&gt;'&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="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;'&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;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2022&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2027&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;q&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;all&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&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;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;TAGS&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API allows about 300 requests a day without a key, and this script makes about 133.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I take from it
&lt;/h2&gt;

&lt;p&gt;If you read a framework's health from Stack Overflow questions, the signal is gone: everything fell by 95% or more. The one thing that still moves is the relative mix, and there native tags held their ground better than React Native and Flutter. What I did not measure: GitHub issues, Reddit, or how many questions now go to AI assistants instead. Where do you look for evidence when you pick a stack?&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>reactnative</category>
      <category>flutter</category>
      <category>data</category>
    </item>
    <item>
      <title>My Read of Four Datasets: Native-Only Looks Like the Weakest Mobile Bet in 2026</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Sun, 01 Nov 2026 08:14:13 +0000</pubDate>
      <link>https://dev.to/5uper0/my-read-of-four-datasets-native-only-looks-like-the-weakest-mobile-bet-in-2026-4pe9</link>
      <guid>https://dev.to/5uper0/my-read-of-four-datasets-native-only-looks-like-the-weakest-mobile-bet-in-2026-4pe9</guid>
      <description>&lt;p&gt;I spent the last week counting public data about mobile: Hacker News hiring threads, the job-seeker threads, Show HN launches and npm installs. This post gives my position on those counts. It is an opinion on partial data, and I mark where each claim comes from and where it stops. Three of the four sources are Hacker News, so they share one audience and do not confirm each other independently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fck3l5mbna905oa445ygm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fck3l5mbna905oa445ygm.png" alt="Bar chart on a log scale showing change since early 2023: iOS mentions in HN hiring posts 0.33 times, iOS seeker posts per hiring post 5.4 times, iOS titles on Show HN 2.7 times, react-native npm downloads 10.8 times, react npm downloads 9.6 times." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The four signals
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Period&lt;/th&gt;
&lt;th&gt;What moved&lt;/th&gt;
&lt;th&gt;Post&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;iOS mentions in HN hiring posts&lt;/td&gt;
&lt;td&gt;2023 H1 to 2026 H2&lt;/td&gt;
&lt;td&gt;19.0 to 6.3 per thread, 0.33x&lt;/td&gt;
&lt;td&gt;&lt;a href="https://veheria.tech/blog/hn-who-is-hiring-native-mobile-vs-ai-46-months/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=opinion-native-only" rel="noopener noreferrer"&gt;hiring threads&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS seeker posts per hiring post&lt;/td&gt;
&lt;td&gt;same&lt;/td&gt;
&lt;td&gt;0.79 to 4.28, 5.4x&lt;/td&gt;
&lt;td&gt;&lt;a href="https://veheria.tech/blog/hn-seekers-vs-hiring-posts-ios-android-46-months/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=opinion-native-only" rel="noopener noreferrer"&gt;seekers&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS titles on Show HN&lt;/td&gt;
&lt;td&gt;same&lt;/td&gt;
&lt;td&gt;10.6 to 29.0 per 30 days, 2.7x&lt;/td&gt;
&lt;td&gt;&lt;a href="https://veheria.tech/blog/show-hn-mobile-launches-vs-mobile-hiring/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=opinion-native-only" rel="noopener noreferrer"&gt;launches&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;react-native npm downloads&lt;/td&gt;
&lt;td&gt;Jan 2023 to Sep 2026&lt;/td&gt;
&lt;td&gt;5.1M to 55.3M a month, 10.8x, control &lt;code&gt;react&lt;/code&gt; 9.6x&lt;/td&gt;
&lt;td&gt;&lt;a href="https://veheria.tech/blog/npm-downloads-react-native-expo-capacitor-46-months/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=opinion-native-only" rel="noopener noreferrer"&gt;npm&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Android moves the same way in the two hiring-side rows: mentions fell 69% and seeker posts per hiring post rose 5.9 times. On Show HN it grew faster than iOS, 4.7 times. Show HN as a whole grew 3.4 times over the same period, so iOS titles took a smaller share of the board (0.91% to 0.74%) while Android took a larger one (0.46% to 0.64%).&lt;/p&gt;

&lt;h2&gt;
  
  
  My position
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Among the stacks I could compare on both sides of the HN threads, native iOS and Android look the weakest.&lt;/strong&gt; They lost the most mentions in hiring posts (about two thirds) and gained the most seeker posts per hiring post (5.4 and 5.9 times). Full stack moved 2.9 times and backend 3.7 times. I left AI out of that comparison because its keyword grew fastest (6.2 times) and is the noisiest. Flutter's mentions in hiring posts fell about as much, from 2.8 to 0.8 per thread, but I did not count Flutter seekers, so I cannot place it. Native is one of the groups getting harder, and in this sample it is furthest along.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The mobile activity I can see did not disappear.&lt;/strong&gt; Show HN titles about iOS and Android kept growing in absolute numbers. Installs of the main cross-platform toolchain rose about ten times, but &lt;code&gt;react&lt;/code&gt; itself rose 9.6 times, so I do not read that as more builders. Whether more distinct people launch mobile apps than in 2023 is untested. What fell is the number of hiring posts that mention iOS or Android. I cannot tell whether those roles ask for native depth alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. React Native sat in the least bad bucket on the two HN hiring-side measures.&lt;/strong&gt; Its mentions in hiring posts fell 14% against 33% for the whole thread, and its seeker posts per hiring post rose 2.0 times against 5.4 for iOS. On Show HN its share of titles fell, on small counts. Expo is the part of the npm data that moved most against the control: its share of &lt;code&gt;react&lt;/code&gt; downloads went from 2.2% to 5.2%. I take that as a reason to be able to show cross-platform work next to native depth. It does not argue for dropping native.&lt;/p&gt;

&lt;h2&gt;
  
  
  What would change my mind
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A larger postings dataset with a clean iOS and Android split that does not show the two-thirds drop. I could not find one for 2025 and 2026, and that gap is why I counted myself.&lt;/li&gt;
&lt;li&gt;October 2026 holding. It was the best month for native hiring in 2026 H2, 11 iOS and 9 Android hiring posts against 3 to 7 in July to September, though 2023 H1 averaged 19 iOS posts per thread. If November and December look like October, the ratio of iOS seeker posts to iOS hiring posts drops toward 3.4 and my 4.3 overstates the squeeze.&lt;/li&gt;
&lt;li&gt;Evidence that Show HN titles grow faster than the number of distinct makers. If one person ships three times as many titles, the launch signal says less than I made it say.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I would do with it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If your CV says iOS or Android and nothing else, add one thing you can show next to it: a cross-platform app or a backend service. The ratios above say those groups moved by smaller factors.&lt;/li&gt;
&lt;li&gt;Compare ratios across groups. Raw npm downloads rose ten times for &lt;code&gt;react&lt;/code&gt; itself, so any single count mostly measures the registry.&lt;/li&gt;
&lt;li&gt;For one sample point: in 2026 H2 on HN, iOS-mentioning seeker posts ran at 4.3 per iOS-mentioning hiring post. That is a ratio of mentions in one corner of the market, and it is no forecast for any single opening.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;All four sources are public and partial. HN skews to startups and to US and remote roles, and three of the four datasets come from it. npm counts include CI and automated installs. A keyword in a post is not an open role.&lt;/li&gt;
&lt;li&gt;The periods differ: HN rows compare 2023 H1 with 2026 H2 averages, npm compares single months (January 2023 and September 2026).&lt;/li&gt;
&lt;li&gt;The seeker ratio is a ratio of two noisy averages. One extra iOS hiring post per thread moves it from 4.3 to 3.7. The iOS hiring average is 6.3 in the first post and 6.2 in the second.&lt;/li&gt;
&lt;li&gt;I did not measure salaries, seniority, location, app store data or anything outside these sources. Each earlier post lists its own limits, and the scripts are in them.&lt;/li&gt;
&lt;li&gt;The counts will be rerun as more months arrive.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Where does your own pipeline disagree with this reading?&lt;/p&gt;

</description>
      <category>opinion</category>
      <category>mobile</category>
      <category>reactnative</category>
      <category>data</category>
    </item>
    <item>
      <title>npm Downloads for React Native, Expo and Capacitor Grew 11 to 23 Times Since 2023. React Grew 10 Times Too</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Sat, 31 Oct 2026 08:13:48 +0000</pubDate>
      <link>https://dev.to/5uper0/npm-downloads-for-react-native-expo-and-capacitor-grew-11-to-23-times-since-2023-react-grew-10-16kk</link>
      <guid>https://dev.to/5uper0/npm-downloads-for-react-native-expo-and-capacitor-grew-11-to-23-times-since-2023-react-grew-10-16kk</guid>
      <description>&lt;p&gt;The &lt;a href="https://veheria.tech/blog/show-hn-mobile-launches-vs-mobile-hiring/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=npm-mobile" rel="noopener noreferrer"&gt;first three posts in this series&lt;/a&gt; used Hacker News: hiring posts, job seekers and launches. This one leaves HN and counts installs. The npm registry publishes daily download counts for every package, so I pulled 46 months for the main cross-platform mobile toolchains that ship through npm: &lt;code&gt;react-native&lt;/code&gt;, &lt;code&gt;expo&lt;/code&gt;, &lt;code&gt;@capacitor/core&lt;/code&gt;, &lt;code&gt;@nativescript/core&lt;/code&gt; and &lt;code&gt;cordova&lt;/code&gt;. I added &lt;code&gt;react&lt;/code&gt; as a control, because a rise in all of them at once says something about npm and not about mobile.&lt;/p&gt;

&lt;p&gt;The three big toolchains grew 11 to 23 times in raw counts, and the control grew 9.6 times. Expo is the one that gained against it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the counts say
&lt;/h2&gt;

&lt;p&gt;Monthly downloads in millions, from the npm downloads API. October 2026 covers 1 to 28 October only.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Month&lt;/th&gt;
&lt;th&gt;react (control)&lt;/th&gt;
&lt;th&gt;react-native&lt;/th&gt;
&lt;th&gt;expo&lt;/th&gt;
&lt;th&gt;@capacitor/core&lt;/th&gt;
&lt;th&gt;cordova&lt;/th&gt;
&lt;th&gt;@nativescript/core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2023-01&lt;/td&gt;
&lt;td&gt;76.4&lt;/td&gt;
&lt;td&gt;5.1&lt;/td&gt;
&lt;td&gt;1.7&lt;/td&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;td&gt;0.25&lt;/td&gt;
&lt;td&gt;0.03&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024-01&lt;/td&gt;
&lt;td&gt;96.7&lt;/td&gt;
&lt;td&gt;8.1&lt;/td&gt;
&lt;td&gt;2.4&lt;/td&gt;
&lt;td&gt;1.6&lt;/td&gt;
&lt;td&gt;0.25&lt;/td&gt;
&lt;td&gt;0.06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025-01&lt;/td&gt;
&lt;td&gt;119.1&lt;/td&gt;
&lt;td&gt;10.6&lt;/td&gt;
&lt;td&gt;3.9&lt;/td&gt;
&lt;td&gt;1.6&lt;/td&gt;
&lt;td&gt;0.16&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-01&lt;/td&gt;
&lt;td&gt;275.4&lt;/td&gt;
&lt;td&gt;18.9&lt;/td&gt;
&lt;td&gt;10.5&lt;/td&gt;
&lt;td&gt;4.7&lt;/td&gt;
&lt;td&gt;0.14&lt;/td&gt;
&lt;td&gt;0.07&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-09&lt;/td&gt;
&lt;td&gt;730.6&lt;/td&gt;
&lt;td&gt;55.3&lt;/td&gt;
&lt;td&gt;38.2&lt;/td&gt;
&lt;td&gt;18.5&lt;/td&gt;
&lt;td&gt;0.25&lt;/td&gt;
&lt;td&gt;0.10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-10 (1 to 28)&lt;/td&gt;
&lt;td&gt;666.0&lt;/td&gt;
&lt;td&gt;51.9&lt;/td&gt;
&lt;td&gt;39.5&lt;/td&gt;
&lt;td&gt;19.4&lt;/td&gt;
&lt;td&gt;0.23&lt;/td&gt;
&lt;td&gt;0.09&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;From January 2023 to September 2026 the multiples are: react 9.6, react-native 10.8, expo 22.7, @capacitor/core 12.1, @nativescript/core 3.1, cordova 1.0.&lt;/p&gt;

&lt;p&gt;The same data as a share of &lt;code&gt;react&lt;/code&gt; downloads in the same month:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Month&lt;/th&gt;
&lt;th&gt;react-native&lt;/th&gt;
&lt;th&gt;expo&lt;/th&gt;
&lt;th&gt;@capacitor/core&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2023-01&lt;/td&gt;
&lt;td&gt;6.70%&lt;/td&gt;
&lt;td&gt;2.21%&lt;/td&gt;
&lt;td&gt;2.00%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024-10 (React Native peak)&lt;/td&gt;
&lt;td&gt;10.12%&lt;/td&gt;
&lt;td&gt;3.17%&lt;/td&gt;
&lt;td&gt;1.48%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-04 (React Native low)&lt;/td&gt;
&lt;td&gt;5.53%&lt;/td&gt;
&lt;td&gt;3.45%&lt;/td&gt;
&lt;td&gt;1.77%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-09&lt;/td&gt;
&lt;td&gt;7.57%&lt;/td&gt;
&lt;td&gt;5.23%&lt;/td&gt;
&lt;td&gt;2.53%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-10 (1 to 28)&lt;/td&gt;
&lt;td&gt;7.80%&lt;/td&gt;
&lt;td&gt;5.93%&lt;/td&gt;
&lt;td&gt;2.91%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Four readings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Absolute counts mostly measure npm.&lt;/strong&gt; &lt;code&gt;react&lt;/code&gt; itself rose 9.6 times. Per day, its downloads were 26% higher in March 2026 than in February 2026, and a smaller step shows in &lt;code&gt;react-native&lt;/code&gt; (+18%). I did not investigate why. Anything that installs packages on a schedule would show up here, so I would not read 10 times more downloads as 10 times more developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expo is the clear relative gainer.&lt;/strong&gt; Against &lt;code&gt;react&lt;/code&gt;, its share went from 2.2% to 5.2% in September 2026 and 5.9% in October. Against &lt;code&gt;react-native&lt;/code&gt; the ratio went from 0.33 to 0.69 and 0.76. Expo apps also depend on &lt;code&gt;react-native&lt;/code&gt;, so the two series overlap and I did not measure by how much.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React Native's share of &lt;code&gt;react&lt;/code&gt; swung, then recovered.&lt;/strong&gt; Its share of &lt;code&gt;react&lt;/code&gt; rose to a peak of 10.1% in October 2024, fell to 5.5% in April 2026 and recovered to 7.8%. That is a swing of nearly a factor of two inside two years, in both directions, and the end point is above where it started.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Capacitor grew slightly faster than the control, Cordova and NativeScript lost ground against it.&lt;/strong&gt; &lt;code&gt;@capacitor/core&lt;/code&gt; grew 12.1 times against 9.6 for &lt;code&gt;react&lt;/code&gt;, with a share between 1.3% and 2.9%. &lt;code&gt;cordova&lt;/code&gt; stayed between 0.14 and 0.25 million a month for the whole window, which is a share of 0.3% falling to 0.03%. &lt;code&gt;@nativescript/core&lt;/code&gt; is tiny: 0.03 million to 0.10 million, 3.1 times against 9.6 for the control.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does and does not say
&lt;/h2&gt;

&lt;p&gt;Package installs are not apps shipped or developers employed. The &lt;a href="https://veheria.tech/blog/hn-who-is-hiring-native-mobile-vs-ai-46-months/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=npm-mobile" rel="noopener noreferrer"&gt;HN hiring posts&lt;/a&gt; showed React Native holding its place while native iOS and Android fell, and the &lt;a href="https://veheria.tech/blog/show-hn-mobile-launches-vs-mobile-hiring/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=npm-mobile" rel="noopener noreferrer"&gt;Show HN counts&lt;/a&gt; showed React Native and Flutter losing share of launch titles. Install counts do not settle that. They say cross-platform JavaScript tooling is installed far more than in 2023 and Expo is growing faster than the rest of it. They do not say who is hired to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Download counts include everything that fetches a tarball: developers, CI runs, mirrors and automated installs. I cannot separate them.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;react&lt;/code&gt; is a control for npm-wide growth, but it also serves the web, so it is an imperfect one.&lt;/li&gt;
&lt;li&gt;One npm package is not a whole framework. &lt;code&gt;@capacitor/core&lt;/code&gt; is the core of Capacitor, not all its plugins.&lt;/li&gt;
&lt;li&gt;Flutter, Kotlin Multiplatform and native Swift do not ship through npm. This post says nothing about them.&lt;/li&gt;
&lt;li&gt;October 2026 is 28 days. Shares are unaffected by that; the absolute row is not comparable to a full month.&lt;/li&gt;
&lt;li&gt;I ran the script twice and the two result sets were identical. The API data may be revised later by npm.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;
&lt;span class="n"&gt;PKGS&lt;/span&gt; &lt;span class="o"&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;react-native&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;expo&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;@capacitor/core&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;@nativescript/core&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;cordova&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;react&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&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;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fail &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;89&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://api.npmjs.org/downloads/range/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;safe&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;downloads&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;day&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;downloads&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;

&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;monthly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&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;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;PKGS&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;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;react&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;m&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;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;PKGS&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API rate-limits quickly, hence the pause and backoff. Data retrieved 2026-10-30.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I take from it
&lt;/h2&gt;

&lt;p&gt;If you choose a cross-platform stack today, npm installs say Expo is where the growth is relative to React Native itself, and Capacitor is growing a little faster than &lt;code&gt;react&lt;/code&gt;. What I did not measure: downloads of Flutter's pub.dev packages, app store listings, or what the installs build. Does the Expo share match what you see in your own projects?&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>reactnative</category>
      <category>javascript</category>
      <category>data</category>
    </item>
    <item>
      <title>Show HN Got More Than Three Times Busier in Three Years. iOS and Android Launches Roughly Kept Pace With It</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Fri, 30 Oct 2026 08:13:22 +0000</pubDate>
      <link>https://dev.to/5uper0/show-hn-got-more-than-three-times-busier-in-three-years-ios-and-android-launches-roughly-kept-pace-4k43</link>
      <guid>https://dev.to/5uper0/show-hn-got-more-than-three-times-busier-in-three-years-ios-and-android-launches-roughly-kept-pace-4k43</guid>
      <description>&lt;p&gt;Two earlier posts counted the jobs side of Hacker News. Mentions of iOS and Android in the monthly &lt;a href="https://veheria.tech/blog/hn-who-is-hiring-native-mobile-vs-ai-46-months/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=show-hn-mobile" rel="noopener noreferrer"&gt;hiring threads fell by about two thirds&lt;/a&gt;, and the &lt;a href="https://veheria.tech/blog/hn-seekers-vs-hiring-posts-ios-android-46-months/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=show-hn-mobile" rel="noopener noreferrer"&gt;number of job seekers per hiring post&lt;/a&gt; rose five to six times for native mobile. The obvious follow-up question is whether people also stopped building mobile apps. The third thing HN can show is what gets launched. "Show HN" is where makers post what they built, so I counted titles with the same method.&lt;/p&gt;

&lt;p&gt;The short answer: mobile launches did not fall. Show HN itself grew so much that iOS and Android launches grew with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the counts say
&lt;/h2&gt;

&lt;p&gt;Show HN stories whose title contains each word, averaged per 30 days so that half-years of different length compare. 2026 H2 covers 1 July to 29 October, 120 days.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Period&lt;/th&gt;
&lt;th&gt;All Show HN&lt;/th&gt;
&lt;th&gt;iOS&lt;/th&gt;
&lt;th&gt;Android&lt;/th&gt;
&lt;th&gt;AI&lt;/th&gt;
&lt;th&gt;Claude&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2023 H1&lt;/td&gt;
&lt;td&gt;1,161&lt;/td&gt;
&lt;td&gt;10.6&lt;/td&gt;
&lt;td&gt;5.3&lt;/td&gt;
&lt;td&gt;145&lt;/td&gt;
&lt;td&gt;0.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2023 H2&lt;/td&gt;
&lt;td&gt;1,153&lt;/td&gt;
&lt;td&gt;10.8&lt;/td&gt;
&lt;td&gt;6.8&lt;/td&gt;
&lt;td&gt;158&lt;/td&gt;
&lt;td&gt;1.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024 H1&lt;/td&gt;
&lt;td&gt;1,353&lt;/td&gt;
&lt;td&gt;11.0&lt;/td&gt;
&lt;td&gt;5.8&lt;/td&gt;
&lt;td&gt;191&lt;/td&gt;
&lt;td&gt;4.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024 H2&lt;/td&gt;
&lt;td&gt;1,534&lt;/td&gt;
&lt;td&gt;8.8&lt;/td&gt;
&lt;td&gt;3.9&lt;/td&gt;
&lt;td&gt;240&lt;/td&gt;
&lt;td&gt;11.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025 H1&lt;/td&gt;
&lt;td&gt;2,063&lt;/td&gt;
&lt;td&gt;18.9&lt;/td&gt;
&lt;td&gt;8.5&lt;/td&gt;
&lt;td&gt;383&lt;/td&gt;
&lt;td&gt;21.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025 H2&lt;/td&gt;
&lt;td&gt;2,581&lt;/td&gt;
&lt;td&gt;21.5&lt;/td&gt;
&lt;td&gt;10.4&lt;/td&gt;
&lt;td&gt;484&lt;/td&gt;
&lt;td&gt;60.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026 H1&lt;/td&gt;
&lt;td&gt;4,303&lt;/td&gt;
&lt;td&gt;36.5&lt;/td&gt;
&lt;td&gt;25.9&lt;/td&gt;
&lt;td&gt;888&lt;/td&gt;
&lt;td&gt;219.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026 H2&lt;/td&gt;
&lt;td&gt;3,896&lt;/td&gt;
&lt;td&gt;29.0&lt;/td&gt;
&lt;td&gt;24.8&lt;/td&gt;
&lt;td&gt;610&lt;/td&gt;
&lt;td&gt;163.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And the same data as a share of all Show HN titles:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Period&lt;/th&gt;
&lt;th&gt;iOS&lt;/th&gt;
&lt;th&gt;Android&lt;/th&gt;
&lt;th&gt;React Native&lt;/th&gt;
&lt;th&gt;Flutter&lt;/th&gt;
&lt;th&gt;AI&lt;/th&gt;
&lt;th&gt;Claude&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2023 H1&lt;/td&gt;
&lt;td&gt;0.91%&lt;/td&gt;
&lt;td&gt;0.46%&lt;/td&gt;
&lt;td&gt;0.11%&lt;/td&gt;
&lt;td&gt;0.20%&lt;/td&gt;
&lt;td&gt;12.5%&lt;/td&gt;
&lt;td&gt;0.04%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2023 H2&lt;/td&gt;
&lt;td&gt;0.93%&lt;/td&gt;
&lt;td&gt;0.59%&lt;/td&gt;
&lt;td&gt;0.16%&lt;/td&gt;
&lt;td&gt;0.21%&lt;/td&gt;
&lt;td&gt;13.7%&lt;/td&gt;
&lt;td&gt;0.11%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024 H1&lt;/td&gt;
&lt;td&gt;0.82%&lt;/td&gt;
&lt;td&gt;0.43%&lt;/td&gt;
&lt;td&gt;0.11%&lt;/td&gt;
&lt;td&gt;0.15%&lt;/td&gt;
&lt;td&gt;14.1%&lt;/td&gt;
&lt;td&gt;0.30%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024 H2&lt;/td&gt;
&lt;td&gt;0.57%&lt;/td&gt;
&lt;td&gt;0.26%&lt;/td&gt;
&lt;td&gt;0.18%&lt;/td&gt;
&lt;td&gt;0.16%&lt;/td&gt;
&lt;td&gt;15.7%&lt;/td&gt;
&lt;td&gt;0.73%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025 H1&lt;/td&gt;
&lt;td&gt;0.92%&lt;/td&gt;
&lt;td&gt;0.41%&lt;/td&gt;
&lt;td&gt;0.07%&lt;/td&gt;
&lt;td&gt;0.10%&lt;/td&gt;
&lt;td&gt;18.6%&lt;/td&gt;
&lt;td&gt;1.02%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025 H2&lt;/td&gt;
&lt;td&gt;0.83%&lt;/td&gt;
&lt;td&gt;0.40%&lt;/td&gt;
&lt;td&gt;0.08%&lt;/td&gt;
&lt;td&gt;0.04%&lt;/td&gt;
&lt;td&gt;18.8%&lt;/td&gt;
&lt;td&gt;2.36%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026 H1&lt;/td&gt;
&lt;td&gt;0.85%&lt;/td&gt;
&lt;td&gt;0.60%&lt;/td&gt;
&lt;td&gt;0.07%&lt;/td&gt;
&lt;td&gt;0.08%&lt;/td&gt;
&lt;td&gt;20.6%&lt;/td&gt;
&lt;td&gt;5.10%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026 H2&lt;/td&gt;
&lt;td&gt;0.74%&lt;/td&gt;
&lt;td&gt;0.64%&lt;/td&gt;
&lt;td&gt;0.06%&lt;/td&gt;
&lt;td&gt;0.06%&lt;/td&gt;
&lt;td&gt;15.7%&lt;/td&gt;
&lt;td&gt;4.19%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Four readings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The board got much busier.&lt;/strong&gt; Show HN went from about 1,160 stories per 30 days in early 2023 to 3,900 to 4,300 in 2026, a factor of 3.4 to 3.7. I did not look into why. More makers, more automated submissions and cheaper building could all do this, and the counts cannot tell them apart.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iOS and Android launches roughly kept pace.&lt;/strong&gt; iOS titles went from 10.6 to 29.0 per 30 days, Android from 5.3 to 24.8. As a share of the board, iOS slipped from 0.91% to 0.74% and Android rose from 0.46% to 0.64%. In absolute terms there are about three times more iOS launch titles per 30 days than in early 2023 and about five times more Android ones. The hiring side moved in the opposite direction over the same period, as the first post showed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React Native and Flutter did not ride the wave.&lt;/strong&gt; Their title counts stayed at roughly 7 to 20 per half-year while the board grew 3.7 times. Flutter's share fell by more than half and React Native's by about a third to a half, on counts too small to lean on. Titles say little about what is under the hood, so I would not read this as a framework ranking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI reached about a fifth of the titles, and Claude went from a handful of titles to thousands.&lt;/strong&gt; "AI" went from 12.5% to 20.6% of titles in the first half of 2026 and 15.7% so far in the second half. "Claude" went from 3 titles in the first half of 2023 to 1,325 in the first half of 2026. The two overlap, so their shares cannot be added.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does and does not say
&lt;/h2&gt;

&lt;p&gt;A launch is not a job. A lot of Show HN is side projects, open-source tools and one-person products, so more mobile launches does not mean more mobile employers. What the three posts show together is a split: the number of mobile launch titles is up, the number of companies posting roles for native mobile engineers is down. I did not test why, and I will not guess in a data post. One hypothesis I would check next is whether the launch count grows faster than the number of distinct makers, because a single person can now ship more titles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Counts are exact-word matches in the title of stories tagged &lt;code&gt;show_hn&lt;/code&gt;, from the HN Algolia API, retrieved 2026-10-29. Stories that Algolia does not index, such as removed ones, are not counted.&lt;/li&gt;
&lt;li&gt;A title that names two terms counts for each, so the columns overlap and must not be added.&lt;/li&gt;
&lt;li&gt;Word matching is on whole words with no prefix matching. My first run used the default prefix matching, which also matches longer words that begin with the search term, and it inflated the AI count by about 4%. Switching it off moved the first-half 2023 AI count from 911 to 874, and the numbers here use the stricter match.&lt;/li&gt;
&lt;li&gt;Only titles are searched. An iOS app whose title says "Show HN: A habit tracker" is not counted.&lt;/li&gt;
&lt;li&gt;2026 H2 has four months of data and uses a per-30-day rate. Short windows move more.&lt;/li&gt;
&lt;li&gt;"Claude" and "AI" are matched as words and I did not read the titles one by one, so some matches may use the word in another sense.&lt;/li&gt;
&lt;li&gt;I did not check how many Show HN stories are written or posted by automation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://hn.algolia.com/api/v1/search_by_date?&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&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;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fail &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&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;tags&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;show_hn&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;hitsPerPage&lt;/span&gt;&lt;span class="sh"&gt;'&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="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;numericFilters&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;created_at_i&amp;gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;,created_at_i&amp;lt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;restrictSearchableAttributes&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;title&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;typoTolerance&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;false&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;queryType&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;prefixNone&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;))[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nbHits&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tzinfo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="n"&gt;WORDS&lt;/span&gt; &lt;span class="o"&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;all&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="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;iOS&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;iOS&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;Android&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;Android&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;React Native&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;React Native&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;Flutter&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;Flutter&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;AI&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;AI&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;Claude&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;Claude&lt;/span&gt;&lt;span class="sh"&gt;'&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;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2025&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2026&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;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="n"&gt;hi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hi&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;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;WORDS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Divide by the number of days in the window and multiply by 30 to get the per-30-day rate in the first table.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I take from it
&lt;/h2&gt;

&lt;p&gt;If you build and ship mobile apps, HN says you are in good company: more mobile launch titles appear every month than in 2023. If you are looking for a salaried mobile role, the hiring threads say there are fewer of them and more people competing. Both can be true at once, and the second one is the one I keep tracking for this series.&lt;/p&gt;

&lt;p&gt;What I did not measure: downloads, revenue, retention or anything outside HN. Does the split between more mobile launches and fewer mobile roles match what you see around you?&lt;/p&gt;

</description>
      <category>hiring</category>
      <category>mobile</category>
      <category>ai</category>
      <category>data</category>
    </item>
    <item>
      <title>On Hacker News, Job Seekers Now Outnumber Hiring Posts 2.3 to 1. For Native iOS and Android It Is 4 to 1</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Thu, 29 Oct 2026 08:12:56 +0000</pubDate>
      <link>https://dev.to/5uper0/on-hacker-news-job-seekers-now-outnumber-hiring-posts-23-to-1-for-native-ios-and-android-it-is-4-1lgk</link>
      <guid>https://dev.to/5uper0/on-hacker-news-job-seekers-now-outnumber-hiring-posts-23-to-1-for-native-ios-and-android-it-is-4-1lgk</guid>
      <description>&lt;p&gt;My &lt;a href="https://veheria.tech/blog/hn-who-is-hiring-native-mobile-vs-ai-46-months/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hn-seekers" rel="noopener noreferrer"&gt;last post&lt;/a&gt; counted the demand side of Hacker News hiring threads: native iOS and Android mentions fell by about two thirds between 2023 and 2026. The first post left one question open: what happened on the other side. Hacker News runs a second monthly thread, "Ask HN: Who wants to be hired?", where people post what they do and what they look for. If hiring posts shrank, did seekers shrink with them?&lt;/p&gt;

&lt;p&gt;They did not. I counted both threads for the same 46 months. Same caveat as before: keyword mentions are not roles, and HN is one corner of the market.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the counts say
&lt;/h2&gt;

&lt;p&gt;Average top-level posts per thread that mention each term, 2023 H1 (six threads) against 2026 H2 so far (four threads, July to October). "Seekers per hiring post" is the seeker average divided by the hiring average.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;Hiring posts, 2023 H1 → 2026 H2&lt;/th&gt;
&lt;th&gt;Seeker posts, 2023 H1 → 2026 H2&lt;/th&gt;
&lt;th&gt;Seekers per hiring post&lt;/th&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;All posts&lt;/td&gt;
&lt;td&gt;371.7 → 248.5&lt;/td&gt;
&lt;td&gt;379.8 → 568.2&lt;/td&gt;
&lt;td&gt;1.02 → 2.29&lt;/td&gt;
&lt;td&gt;×2.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS&lt;/td&gt;
&lt;td&gt;19.0 → 6.2&lt;/td&gt;
&lt;td&gt;15.0 → 26.8&lt;/td&gt;
&lt;td&gt;0.79 → 4.28&lt;/td&gt;
&lt;td&gt;×5.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;18.8 → 5.8&lt;/td&gt;
&lt;td&gt;12.7 → 22.8&lt;/td&gt;
&lt;td&gt;0.67 → 3.96&lt;/td&gt;
&lt;td&gt;×5.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Native&lt;/td&gt;
&lt;td&gt;11.3 → 9.8&lt;/td&gt;
&lt;td&gt;23.7 → 40.2&lt;/td&gt;
&lt;td&gt;2.09 → 4.13&lt;/td&gt;
&lt;td&gt;×2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Any mobile term&lt;/td&gt;
&lt;td&gt;54.5 → 26.2&lt;/td&gt;
&lt;td&gt;65.8 → 102.0&lt;/td&gt;
&lt;td&gt;1.21 → 3.89&lt;/td&gt;
&lt;td&gt;×3.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full stack&lt;/td&gt;
&lt;td&gt;93.5 → 58.8&lt;/td&gt;
&lt;td&gt;88.5 → 162.2&lt;/td&gt;
&lt;td&gt;0.95 → 2.76&lt;/td&gt;
&lt;td&gt;×2.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;89.7 → 56.8&lt;/td&gt;
&lt;td&gt;81.2 → 187.2&lt;/td&gt;
&lt;td&gt;0.91 → 3.30&lt;/td&gt;
&lt;td&gt;×3.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI or LLM&lt;/td&gt;
&lt;td&gt;55.2 → 144.5&lt;/td&gt;
&lt;td&gt;18.8 → 307.5&lt;/td&gt;
&lt;td&gt;0.34 → 2.13&lt;/td&gt;
&lt;td&gt;×6.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In early 2023 the two threads were the same size, about 375 posts each. By autumn 2026 hiring posts per thread are down a third and seeker posts are up by half. October 2026 has the largest seeker thread in the whole window, 693 posts against 263 hiring posts.&lt;/p&gt;

&lt;p&gt;Three readings, in order of how well the data supports them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Native iOS and Android got hit hardest.&lt;/strong&gt; Seeker posts that mention iOS went from 0.8 per hiring post to 4.3, and Android from 0.7 to 4.0. That is a 5.4 and 5.9 times change against 2.2 for the whole thread. Both numbers move the same way. They overlap, since many posts mention both, so they are one signal and not two.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React Native is the one mobile term that held.&lt;/strong&gt; It started with more seekers than hiring posts (2.1) and ended at 4.1, a 2.0 times change, slightly less than the thread average. Part of that is a high starting base: a lot of seekers already listed React Native in 2023. It means React Native did no worse than the market, which is a low bar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mobile as a whole is not much worse than full stack.&lt;/strong&gt; Any-mobile moved 3.2 times, full stack 2.9 times and backend 3.7 times. If you hold the view that mobile fell off a cliff while full stack stayed fine, this sample does not support it. Native mobile fell off a cliff. Full stack and backend also lost hiring posts and gained seekers, by a smaller factor than native.&lt;/p&gt;

&lt;p&gt;The AI row grew the most, 6.2 times, but it is the least trustworthy one. Seekers can add "AI" to a skill line and hiring posts add it to company blurbs, so both sides can inflate the keyword.&lt;/p&gt;

&lt;p&gt;Monthly counts for 2026 H2, so the October figures above can be checked:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Month&lt;/th&gt;
&lt;th&gt;Hiring posts&lt;/th&gt;
&lt;th&gt;iOS&lt;/th&gt;
&lt;th&gt;Android&lt;/th&gt;
&lt;th&gt;Seeker posts&lt;/th&gt;
&lt;th&gt;iOS&lt;/th&gt;
&lt;th&gt;Android&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2026-07&lt;/td&gt;
&lt;td&gt;257&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;489&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-08&lt;/td&gt;
&lt;td&gt;226&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;555&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-09&lt;/td&gt;
&lt;td&gt;248&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;536&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026-10&lt;/td&gt;
&lt;td&gt;263&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;693&lt;/td&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Counts are keyword mentions in free-text posts. A seeker who writes "iOS, Android, React Native, Python" counts once for each term, whether or not they want a mobile job.&lt;/li&gt;
&lt;li&gt;A seeker thread is self-selected. I assume people who post there skew toward those without a quick alternative, but I have no data on that. It measures supply and not open roles, and I did not check how many seeker posts are duplicates or automated.&lt;/li&gt;
&lt;li&gt;The 2026 H2 average uses four threads, 2023 H1 uses six. October 2026 is a single large seeker thread. Without it the all-posts ratio is 2.16 instead of 2.29, iOS 5.0, Android 4.5, React Native 3.65. Native goes up because October was the best month for native hiring in the window, 11 iOS and 9 Android hiring posts against 3 to 7 in July to September. The monthly counts are below.&lt;/li&gt;
&lt;li&gt;Ratios of two noisy averages are noisy. iOS and Android hiring posts are about 6 per thread now, so one extra iOS post per thread moves the iOS ratio from 4.3 to 3.7.&lt;/li&gt;
&lt;li&gt;This is HN only. &lt;a href="https://hiringlab.indeed.com/2025/07/30/the-us-tech-hiring-freeze-continues/" rel="noopener noreferrer"&gt;Indeed Hiring Lab&lt;/a&gt; reports similar direction and size for Android and iOS postings on a different baseline, and that is the cross-check I have, not a confirmation of the ratio.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Method
&lt;/h2&gt;

&lt;p&gt;Same source as the first post: HN Algolia API, threads by the &lt;code&gt;whoishiring&lt;/code&gt; account, created on or after 2023-01-01, retrieved 2026-10-28, top-level comments only, one count per post per term. The script takes the thread title prefix as a parameter, so it covers both kinds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://hn.algolia.com/api/v1/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&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;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fail &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;search_by_date?&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="s"&gt;Ask HN: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="si"&gt;}&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;tags&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;story,author_whoishiring&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;hitsPerPage&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;page&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hits&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nbPages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Ask HN: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;created_at&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2023-01-01&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;created_at&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;P&lt;/span&gt; &lt;span class="o"&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;iOS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\bios\b&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;Android&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\bandroid\b&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;React Native&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;react[ -]native&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;full stack&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;full[ -]?stack&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;backend&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;back[ -]?end&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;AI/LLM&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\bai\b|\bllms?\b|\bgenerative\b&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;any mobile&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\bios\b|\bandroid\b|react[ -]native|\bflutter\b|\bswiftui\b|\bkotlin\b|\bmobile\b&lt;/span&gt;&lt;span class="sh"&gt;'&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;prefix&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;Who is hiring&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;Who wants to be hired&lt;/span&gt;&lt;span class="sh"&gt;'&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;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;objectID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;search_by_date?&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tags&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;comment,story_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="si"&gt;}&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;hitsPerPage&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;page&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;
            &lt;span class="n"&gt;txt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;comment_text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;''&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;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hits&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;parent_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pg&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nbPages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;
            &lt;span class="n"&gt;pg&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&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;thread&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;month&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;created_at&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;top_level&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;txt&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&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;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()})&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I take from it
&lt;/h2&gt;

&lt;p&gt;For someone whose résumé says iOS or Android and nothing else, the HN numbers show about four seeker posts per hiring post, up five to six times since 2023. A candidate who can also show React Native or backend work sits in the buckets that moved less. AI moved the most, for the reason above. That matches the shape of the first post, and I would still not treat HN as the whole market.&lt;/p&gt;

&lt;p&gt;What I did not measure: seniority of the seekers, how many posts got a reply, location, or anything outside HN. If you hire mobile engineers, does a ratio of about four candidates per native opening match what you see in your own pipeline?&lt;/p&gt;

</description>
      <category>hiring</category>
      <category>mobile</category>
      <category>ai</category>
      <category>data</category>
    </item>
    <item>
      <title>I Counted 46 Months of HN "Who Is Hiring": Native Mobile Fell by Two Thirds, React Native Did Not</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Wed, 28 Oct 2026 08:12:35 +0000</pubDate>
      <link>https://dev.to/5uper0/i-counted-46-months-of-hn-who-is-hiring-native-mobile-fell-by-two-thirds-react-native-did-not-1406</link>
      <guid>https://dev.to/5uper0/i-counted-46-months-of-hn-who-is-hiring-native-mobile-fell-by-two-thirds-react-native-did-not-1406</guid>
      <description>&lt;p&gt;Everyone in mobile has a feeling that the market got worse. I wanted a number that someone else could rerun, so I counted. The source is the monthly "Ask HN: Who is hiring?" thread on Hacker News, from January 2023 to October 2026: 46 threads, about 15,000 top-level job posts. A keyword in a post is not an open role, and HN skews toward startups, so treat this as one sample of one corner of the market. Inside that corner, the result is clearer than I expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the counts say
&lt;/h2&gt;

&lt;p&gt;I compared the first six threads (January to June 2023) with the four most recent (July to October 2026). Average number of top-level posts per thread that mention each term:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Term&lt;/th&gt;
&lt;th&gt;2023 H1&lt;/th&gt;
&lt;th&gt;2026 H2 so far&lt;/th&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;All posts&lt;/td&gt;
&lt;td&gt;371.7&lt;/td&gt;
&lt;td&gt;248.5&lt;/td&gt;
&lt;td&gt;-33%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS&lt;/td&gt;
&lt;td&gt;19.0&lt;/td&gt;
&lt;td&gt;6.3&lt;/td&gt;
&lt;td&gt;-67%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android&lt;/td&gt;
&lt;td&gt;18.8&lt;/td&gt;
&lt;td&gt;5.8&lt;/td&gt;
&lt;td&gt;-69%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React Native&lt;/td&gt;
&lt;td&gt;11.3&lt;/td&gt;
&lt;td&gt;9.8&lt;/td&gt;
&lt;td&gt;-14%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Any mobile term&lt;/td&gt;
&lt;td&gt;54.5&lt;/td&gt;
&lt;td&gt;26.3&lt;/td&gt;
&lt;td&gt;-52%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full stack&lt;/td&gt;
&lt;td&gt;93.5&lt;/td&gt;
&lt;td&gt;58.8&lt;/td&gt;
&lt;td&gt;-37%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;89.7&lt;/td&gt;
&lt;td&gt;56.8&lt;/td&gt;
&lt;td&gt;-37%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI or LLM&lt;/td&gt;
&lt;td&gt;55.2&lt;/td&gt;
&lt;td&gt;144.5&lt;/td&gt;
&lt;td&gt;+162%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three things stand out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Native iOS and Android mentions fell by roughly two thirds.&lt;/strong&gt; That is twice the drop in overall thread volume. React Native fell by 14%, less than the thread itself, so in this sample React Native kept its place while native lost it. Flutter, the other big cross-platform name, fell as much as native, from 2.8 to 0.8 posts per thread, so this is not a general cross-platform result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full stack and backend fell about as much as the thread did, 37% against 33%.&lt;/strong&gt; Mobile as a whole fell 52%, so it lost more than the general web roles, but not by an order of magnitude. If you expected full stack to be booming while mobile collapsed, HN does not show that. Both shrank.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI is the only bucket that grew.&lt;/strong&gt; Mentions of "AI" or "LLM" went from 14.8% of posts in the first half of 2023 to 58.1% in the second half of 2026. Part of that is company descriptions ("an AI-powered platform for...") and not roles. It still tells you what a hiring post has to say about itself today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Share of posts, by half-year
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Period&lt;/th&gt;
&lt;th&gt;Any mobile term&lt;/th&gt;
&lt;th&gt;Full stack&lt;/th&gt;
&lt;th&gt;Backend&lt;/th&gt;
&lt;th&gt;AI or LLM&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2023 H1&lt;/td&gt;
&lt;td&gt;14.7%&lt;/td&gt;
&lt;td&gt;25.2%&lt;/td&gt;
&lt;td&gt;24.1%&lt;/td&gt;
&lt;td&gt;14.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2023 H2&lt;/td&gt;
&lt;td&gt;11.8%&lt;/td&gt;
&lt;td&gt;25.2%&lt;/td&gt;
&lt;td&gt;21.0%&lt;/td&gt;
&lt;td&gt;22.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024 H1&lt;/td&gt;
&lt;td&gt;10.8%&lt;/td&gt;
&lt;td&gt;26.8%&lt;/td&gt;
&lt;td&gt;22.9%&lt;/td&gt;
&lt;td&gt;26.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024 H2&lt;/td&gt;
&lt;td&gt;11.7%&lt;/td&gt;
&lt;td&gt;27.3%&lt;/td&gt;
&lt;td&gt;24.9%&lt;/td&gt;
&lt;td&gt;33.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025 H1&lt;/td&gt;
&lt;td&gt;12.5%&lt;/td&gt;
&lt;td&gt;29.7%&lt;/td&gt;
&lt;td&gt;26.0%&lt;/td&gt;
&lt;td&gt;41.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025 H2&lt;/td&gt;
&lt;td&gt;9.9%&lt;/td&gt;
&lt;td&gt;29.3%&lt;/td&gt;
&lt;td&gt;27.6%&lt;/td&gt;
&lt;td&gt;50.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026 H1&lt;/td&gt;
&lt;td&gt;11.9%&lt;/td&gt;
&lt;td&gt;28.1%&lt;/td&gt;
&lt;td&gt;26.8%&lt;/td&gt;
&lt;td&gt;54.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026 H2 (4 threads)&lt;/td&gt;
&lt;td&gt;10.6%&lt;/td&gt;
&lt;td&gt;23.6%&lt;/td&gt;
&lt;td&gt;22.8%&lt;/td&gt;
&lt;td&gt;58.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;As a share of posts, mobile dropped from 14.7% to about 12% by the second half of 2023 and then stayed roughly flat. Most of the share loss happened in 2023. The absolute numbers kept falling after that because the threads themselves shrank.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this sits next to other sources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hiringlab.indeed.com/2025/07/30/the-us-tech-hiring-freeze-continues/" rel="noopener noreferrer"&gt;Indeed Hiring Lab&lt;/a&gt; reported in July 2025 that Android, Java, .NET and iOS developer postings were all down by more than 60% compared with early 2020. HN is a different sample on a different baseline, but the direction and size for iOS and Android match. Indeed also says ML engineer postings were up 59% from early 2020.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://newsletter.pragmaticengineer.com/i/201325168/3-mobile-and-frontend-demand-drops-ai-and-fde-surges" rel="noopener noreferrer"&gt;The Pragmatic Engineer&lt;/a&gt; wrote in June 2026 that frontend titles are disappearing fastest, followed by native iOS and Android ones. The article puts AI engineering openings up 60% in a year at top companies, against 7% for software engineering overall.&lt;/p&gt;

&lt;p&gt;I looked for a public dataset that splits iOS and Android from backend and full stack for 2025 and 2026 and did not find one. Indeed groups them, the Pragmatic Engineer chart is paywalled, BLS has no mobile category, and the Stack Overflow developer-type pages I tried returned 404. That gap is part of why I counted myself. My earlier &lt;a href="https://veheria.tech/mobile-market-2026/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=hn-hiring" rel="noopener noreferrer"&gt;mobile hiring write-up&lt;/a&gt; covers the rest of the picture: the rebound is senior-led, and pay splits by level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method and limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Source: the HN Algolia API, threads by the &lt;code&gt;whoishiring&lt;/code&gt; account whose title starts with "Ask HN: Who is hiring", created on or after 2023-01-01. Retrieved 2026-10-27. October 2026 is mostly complete, so the 2026 H2 figures use four threads.&lt;/li&gt;
&lt;li&gt;Only top-level comments count (the parent is the thread). A post counts once per term, however many times it uses it.&lt;/li&gt;
&lt;li&gt;"Any mobile term" is &lt;code&gt;ios&lt;/code&gt;, &lt;code&gt;android&lt;/code&gt;, &lt;code&gt;react native&lt;/code&gt;, &lt;code&gt;flutter&lt;/code&gt;, &lt;code&gt;swiftui&lt;/code&gt;, &lt;code&gt;kotlin&lt;/code&gt; or &lt;code&gt;mobile&lt;/code&gt;. The AI term is &lt;code&gt;ai&lt;/code&gt;, &lt;code&gt;llm&lt;/code&gt;, &lt;code&gt;llms&lt;/code&gt; or &lt;code&gt;generative&lt;/code&gt;. The last one is noisy, because it also matches mobile web and mobile phones as a product. The iOS and Android rows are the cleaner signal.&lt;/li&gt;
&lt;li&gt;A keyword in a post is not an open role. "AI" shows up in company blurbs. HN skews to US and remote startups, not to the broader market. Dead and deleted comments may be missing from Algolia.&lt;/li&gt;
&lt;li&gt;I ran the script twice. The second run reproduced the same counts for the months I compared.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The script is short enough to read in full:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://hn.algolia.com/api/v1/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&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;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SystemExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;fail &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;search_by_date?&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;query&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;Ask HN: Who is hiring&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;tags&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;story,author_whoishiring&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;hitsPerPage&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;page&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hits&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nbPages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;threads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;threads&lt;/span&gt;
           &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Ask HN: Who is hiring&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;created_at&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;2023-01-01&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;created_at&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="n"&gt;P&lt;/span&gt; &lt;span class="o"&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;iOS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\bios\b&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;Android&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\bandroid\b&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;React Native&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;react[ -]native&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;Flutter&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\bflutter\b&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;full stack&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;full[ -]?stack&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;backend&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;back[ -]?end&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;AI/LLM&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\bai\b|\bllms?\b|\bgenerative\b&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;any mobile&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\bios\b|\bandroid\b|react[ -]native|\bflutter\b|\bswiftui\b|\bkotlin\b|\bmobile\b&lt;/span&gt;&lt;span class="sh"&gt;'&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;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;threads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;objectID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;search_by_date?&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;urlencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tags&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;comment,story_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="si"&gt;}&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;hitsPerPage&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;page&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;
        &lt;span class="n"&gt;txt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;comment_text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;''&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;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hits&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;parent_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;tid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pg&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;nbPages&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="n"&gt;pg&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&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;month&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;created_at&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;top_level&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;txt&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;I&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;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()})&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I take from it
&lt;/h2&gt;

&lt;p&gt;For someone choosing a specialty, native depth alone is the weakest position in this sample, and most of the share loss came in 2023. React Native held up better than iOS or Android taken alone, while Flutter did not. Posts that mention AI are now the majority, and I read that as a sign that being able to show how you ship with coding agents matters more than it did in 2023.&lt;/p&gt;

&lt;p&gt;What I did not measure: salaries, seniority, remote versus on-site, or anything outside HN. If you have a larger postings dataset with an iOS and Android split, I would like to see whether it shows the same two-thirds drop. Does it match what you see in your own hiring?&lt;/p&gt;

</description>
      <category>hiring</category>
      <category>mobile</category>
      <category>ai</category>
      <category>data</category>
    </item>
    <item>
      <title>Mobile hiring in 2026: fewer jobs, higher bar – what the data says</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Tue, 20 Oct 2026 14:35:48 +0000</pubDate>
      <link>https://dev.to/5uper0/mobile-hiring-in-2026-fewer-jobs-higher-bar-what-the-data-says-3m2c</link>
      <guid>https://dev.to/5uper0/mobile-hiring-in-2026-fewer-jobs-higher-bar-what-the-data-says-3m2c</guid>
      <description>&lt;p&gt;People spent about $85 billion on non-game apps in 2025, up 21% (Sensor Tower, via TechCrunch, January 2026). It was the first year consumers spent more on apps than on games. Demand for mobile products is not falling.&lt;/p&gt;

&lt;p&gt;Hiring for the people who build them is. Indeed Hiring Lab reported in July 2025 that iOS, Android, Java and .NET developer postings were each down more than 60% against early 2020, while software postings overall were down 49%. That is a US figure from mid-2025, and I have not found a 2026 mobile-only number. The broader index tells the same story: US software development postings stood at 74.4 in August 2026 against a February 2020 baseline of 100 (Indeed, August 2026).&lt;/p&gt;

&lt;p&gt;So the market is smaller. But the more interesting fact is who it is smaller for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The rebound is senior.&lt;/strong&gt; From May 2025 to May 2026 software postings recovered, and senior roles made up 71% of that net increase (Indeed Hiring Lab, July 2026). Entry-level hiring did not come back: SignalFire's 2026 talent report has new-graduate hiring at large tech companies about 65% below 2019. A Stanford study finds employment of 22–25-year-olds in AI-exposed jobs 19% below trend, with no comparable gap for experienced workers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The engineering mix is shifting.&lt;/strong&gt; SignalFire's 2026 report has the AI/ML engineer share up 39% since ChatGPT and the front-end share down about 25%. Cross-platform keeps taking first versions: Flutter and React Native together accounted for roughly one in five new apps released in 2024 (Pragmatic Engineer).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The easy money is gone.&lt;/strong&gt; Postings peaked in early 2022 and fell when zero interest rates ended (Indeed). Layoffs removed more than 150,000 tech jobs in 2024 alone (Layoffs.fyi via TechCrunch). Companies that kept shipping did it with flatter teams: at large tech firms an engineering manager now covers about 12 engineers, up from 10 (SignalFire).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Applying became a lottery.&lt;/strong&gt; Applications per opening roughly doubled between 2022 and 2024 (Greenhouse, +102%). LinkedIn took about 11,000 applications a minute in mid-2025, and three quarters of US job seekers now use AI on their applications (Fortune, November 2025). A posting is not always evidence of a vacancy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means if you build mobile apps for a living&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The data does not say "mobile is dead". It says the market rewards a different profile than 2021 did.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aim at the level the rebound is paying for.&lt;/strong&gt; Senior roles were 71% of the net growth in postings; entry-level hiring at large tech firms is about 65% below 2019. Staff, lead and architect scope gets the openings. A "Senior iOS" title with feature-ticket scope competes with the largest pool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Show AI-assisted delivery, not AI curiosity.&lt;/strong&gt; AI/ML engineer share is up 39% in the engineering mix. Teams ask how you ship faster and safer with coding agents: review gates, tests, release discipline. Put one concrete example on your profile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be reachable by people, not forms.&lt;/strong&gt; Applications per opening doubled in two years and three quarters of applicants use AI. A form entry is one of hundreds. A short note to the engineering lead or a recruiter who places mobile roles, naming one specific problem you solve, beats the form.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-platform is a skill to add, not a threat to fight.&lt;/strong&gt; Flutter and React Native were roughly one in five new apps in 2024. Native depth plus the ability to judge where sharing code is worth it is the senior-level skill.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What this means if you run a team that has to ship a mobile app&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The scarce thing is not applicants. It is senior mobile judgment: someone who can decide what to build natively, what to share, how to keep releases boring, and how to use AI coding tools without lowering the bar. Those people exist, but in my experience they rarely come through a job board. For a team stuck in a six-month search, the fastest fix is often to bring senior mobile judgment in early, before the permanent hire, for example by promoting an internal lead or involving an experienced reviewer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I would watch next&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A 2026 mobile-only postings figure. Indeed's last one is from July 2025.&lt;/li&gt;
&lt;li&gt;Whether AI coding tools change the shape of mobile teams more than the size: fewer juniors, more senior reviewers.&lt;/li&gt;
&lt;li&gt;Europe. Indeed notes Germany and France did not follow the rebound, and I could not find a reliable Spain-specific mobile number. If you have one, I would like to see it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The numbers, with sources and dates, are on one page: &lt;a href="https://veheria.tech/mobile-market-2026/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=mobile-market-2026" rel="noopener noreferrer"&gt;https://veheria.tech/mobile-market-2026/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=mobile-market-2026&lt;/a&gt; (that is the full write-up).&lt;/p&gt;

</description>
      <category>mobile</category>
      <category>ios</category>
      <category>android</category>
      <category>hiring</category>
    </item>
    <item>
      <title>Modularizing a Legacy iOS App Without Stopping Delivery</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Sat, 05 Sep 2026 09:34:17 +0000</pubDate>
      <link>https://dev.to/5uper0/modularizing-a-legacy-ios-app-without-stopping-delivery-2k2l</link>
      <guid>https://dev.to/5uper0/modularizing-a-legacy-ios-app-without-stopping-delivery-2k2l</guid>
      <description>&lt;p&gt;I spent a year migrating a smart-pet-device company's app off a single-target Objective-C codebase, module by module, while the team kept shipping releases the entire time. No feature freeze, no six-month rewrite branch nobody could merge back. +30% on performance and UX metrics by the end, and every release in between still went out on schedule.&lt;/p&gt;

&lt;p&gt;Modularization gets sold as a build-time problem: split the app so Xcode compiles faster. That part's real, but it's not what makes it hard. The hard part is deciding where the boundaries actually go, because a wrong one costs you for years, and the stop-the-world rewrite to fix it later is exactly the thing you were trying to avoid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boundaries follow ownership, not folders
&lt;/h2&gt;

&lt;p&gt;The obvious move is modularizing along the existing folder structure: pull &lt;code&gt;Networking/&lt;/code&gt; into a module, then &lt;code&gt;UI/&lt;/code&gt;, then &lt;code&gt;Models/&lt;/code&gt;. That produces modules that compile a bit faster and change nothing else, because the coupling that used to be implicit inside one target is now explicit across module boundaries, and just as tight.&lt;/p&gt;

&lt;p&gt;The boundary that actually held on this migration was the one that followed who owned the code and how often it changed independently: a screen's data layer, its business logic, and its UI moved together as one unit, because that's the unit a single engineer or pair actually shipped changes to. A "shared utilities" module everyone imports and nobody owns is where modularization efforts go to die. It becomes a second monolith with extra ceremony bolted on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extract the smallest thing first, not the biggest
&lt;/h2&gt;

&lt;p&gt;The natural first move is pulling out the biggest, most obviously reusable piece: the design system, the networking layer. Those are the wrong first extractions, because they're also the pieces with the most existing call sites, so proving the approach means touching the most files before you've proven anything.&lt;/p&gt;

&lt;p&gt;The extraction that actually de-risks the migration is the smallest, most isolated feature module with the fewest dependents. Get its public interface defined, its internals hidden, and ship it in a real release. That's the proof the rest of the migration reuses. Start with the design system instead, and when something breaks in week three you can't tell whether it's the modularization approach or the size of the diff.&lt;/p&gt;

&lt;h2&gt;
  
  
  The interim is the project, not a phase you pass through
&lt;/h2&gt;

&lt;p&gt;A half-modularized app has a monolith target and a growing set of extracted modules depending on each other in ways nobody fully mapped. Every new feature during that stretch has to decide whether it belongs in the module structure or the legacy target, and whether that decision gets revisited when the module graph shifts next month. Budget the interim with an explicit exit criterion. "60% modularized" isn't a real number when nobody's diagrammed the dependency graph it's measured against.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually breaks delivery mid-migration
&lt;/h2&gt;

&lt;p&gt;Build times regress briefly while modules settle into their real dependency graph. Merge conflicts cluster in whatever file every module still touches, usually the app's root composition point, until that gets its own clear owner too. And team confidence dips: engineers who've shipped fast in the old monolith for years feel slower for a few sprints inside the new boundaries, before the structure starts paying that speed back. Name that dip to the team before it happens, not after someone asks why velocity looks worse this sprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  The discipline that holds
&lt;/h2&gt;

&lt;p&gt;Define a module's public interface before extracting its implementation. Ship one small module fully, in a real release, before touching a second. Track the interim as its own workstream with an exit criterion. And accept that the ownership map, not the folder structure, is what decides where a boundary actually goes.&lt;/p&gt;

&lt;p&gt;If you're staring at a monolithic codebase and a roadmap that can't pause for a rewrite, that's exactly the kind of call I help teams make in a &lt;a href="https://veheria.tech/work/" rel="noopener noreferrer"&gt;strategy session&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What's the module in your own codebase that everyone agrees should be split out, and what's actually stopping the team from starting?&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://veheria.tech/blog/modularizing-legacy-ios-app/" rel="noopener noreferrer"&gt;veheria.tech/blog/modularizing-legacy-ios-app&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>architecture</category>
      <category>engineering</category>
      <category>legacy</category>
    </item>
    <item>
      <title>n8n vs Custom Code for Engineering Automation: The Decision, and the Bug That Proved It Right</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Fri, 04 Sep 2026 09:16:25 +0000</pubDate>
      <link>https://dev.to/5uper0/n8n-vs-custom-code-for-engineering-automation-the-decision-and-the-bug-that-proved-it-right-3a8l</link>
      <guid>https://dev.to/5uper0/n8n-vs-custom-code-for-engineering-automation-the-decision-and-the-bug-that-proved-it-right-3a8l</guid>
      <description>&lt;p&gt;I built the pipeline that publishes this site's content in versioned code instead of n8n. Not a philosophical stance against no-code tools, a practical call, and one specific bug is why I still think it was the right one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why code, not a canvas
&lt;/h2&gt;

&lt;p&gt;Four reasons drove it, in order of how much they actually mattered:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Review parity.&lt;/strong&gt; Every change to how a post gets approved or published goes through the same PR review as the rest of the site. A workflow-canvas change doesn't get that by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Headless operation.&lt;/strong&gt; Claude Code drives the queue directly, no GUI dashboard sitting between the agent and the task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Existing infrastructure.&lt;/strong&gt; A Telegram bot already handled approvals; there was no gap a workflow tool needed to fill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One fewer service.&lt;/strong&gt; Every extra tool in the stack is something else to patch and keep secure. Skipping it was the cheap option, not just the principled one.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The bug that proved it
&lt;/h2&gt;

&lt;p&gt;On July 20, 2026, a scheduled post silently failed. The Buffer API adapter treated an error response as a normal one, never checked the status, so the X post never actually went out while the pipeline marked it published. Nothing threw, nothing alerted, the queue just quietly lied about what had shipped.&lt;/p&gt;

&lt;p&gt;I found it the way you'd expect: read &lt;code&gt;buffer.py&lt;/code&gt;, saw exactly where the status check was missing, fixed one line. Cheap once you can see it.&lt;/p&gt;

&lt;p&gt;That's the part I can't picture happening the same way in a workflow canvas. I genuinely don't have a mental model for debugging that failure mode there, a canvas doesn't hand you the same thing a stack trace and &lt;code&gt;git blame&lt;/code&gt; hand you in code. You'd be reading node configuration and hoping the tool's own logging caught the edge case, instead of reading the exact line that skipped a check.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this is actually about
&lt;/h2&gt;

&lt;p&gt;It isn't code versus no-code as a philosophy. It's about legibility when automation is wrong in a way that doesn't throw an error. A silent-fail bug is the worst kind, because nothing tells you to go look. The only thing that saved this one was that the fix path was a normal code review, on a normal file, in a language with a debugger and a blame command. That's a property of the tool, not of how careful I was that week.&lt;/p&gt;

&lt;p&gt;If your automation stack can fail without telling you, the question worth asking isn't whether the tool is fast to build in. It's whether you'd actually be able to find the bug when it goes quiet.&lt;/p&gt;

&lt;p&gt;If you're weighing a workflow tool against custom code for something that publishes or ships on your behalf, that's exactly the kind of tradeoff I help teams think through in a &lt;a href="https://veheria.tech/work/" rel="noopener noreferrer"&gt;strategy session&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What's the automation in your own stack you'd have the hardest time debugging if it started failing silently?&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://veheria.tech/blog/n8n-vs-custom-agents-engineering-ops/" rel="noopener noreferrer"&gt;veheria.tech/blog/n8n-vs-custom-agents-engineering-ops&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>productivity</category>
    </item>
    <item>
      <title>CLAUDE.md for an iOS Team: What to Put In It (and What to Leave Out)</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Fri, 04 Sep 2026 09:16:07 +0000</pubDate>
      <link>https://dev.to/5uper0/claudemd-for-an-ios-team-what-to-put-in-it-and-what-to-leave-out-23pp</link>
      <guid>https://dev.to/5uper0/claudemd-for-an-ios-team-what-to-put-in-it-and-what-to-leave-out-23pp</guid>
      <description>&lt;p&gt;My first CLAUDE.md for a client project ran 400 lines: architecture diagrams, the full MVVM-vs-TCA debate, a style section that just repeated SwiftLint's config in prose. Claude Code reads that file in full on every single turn, and it still missed rules buried near the bottom, because by line 340 they're competing with everything else for the model's attention. I cut it to 60 lines over two weeks. Same team, same codebase, fewer violations of the rules that actually mattered.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's not documentation
&lt;/h2&gt;

&lt;p&gt;The instinct is to treat CLAUDE.md like a README: a place to record everything true about the project. A README gets read once by a human who skims for the one section they need. CLAUDE.md gets read in full, by a model, every turn, and every line you add dilutes every other line's share of attention. That's the whole design constraint, and most CLAUDE.md files ignore it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What earns a line
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Non-obvious conventions.&lt;/strong&gt; Not "we use MVVM," that's visible in five minutes of reading the code. "ViewModels never import UIKit" earns its place only if it's a rule someone actually broke once and it cost a day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraints invisible in the diff.&lt;/strong&gt; App Store review requirements, a minimum OS version the code doesn't yet reflect, a performance budget on one screen because a past ship got rejected for jank. An agent has no way to infer any of that from the code alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repo-specific workflow gotchas.&lt;/strong&gt; Which branch triggers a real deploy, which test suite is a known-flaky non-gate versus a hard one, where the actual source of truth lives when two files disagree. I run a merge gate across a few of my own repos, code only merges once CI is green and review found nothing blocking, and the single highest-value line in each CLAUDE.md is the sentence explaining that the gate exists and why a raw &lt;code&gt;git merge&lt;/code&gt; is bypassing something on purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the agent never touches unsupervised.&lt;/strong&gt; For me that's deploy config and anything security-sensitive. Naming the boundary explicitly is cheaper than discovering it was needed after something already broke.&lt;/p&gt;

&lt;h2&gt;
  
  
  What doesn't
&lt;/h2&gt;

&lt;p&gt;Anything git blame or the README already answers. Aspirational rules no linter enforces, an unenforced rule just teaches the model that the file's rules are optional. Architecture history and rationale, useful for onboarding a human, irrelevant to the task in front of the agent right now. Anything a linter or type system already blocks mechanically; if SwiftLint already kills force-unwraps, writing "avoid force-unwraps" adds length, not signal.&lt;/p&gt;

&lt;p&gt;The before/after: the 400-line version spelled out the Git branching strategy, every third-party dependency and why it was picked, and a style section duplicating the linter. The 60-line version points at the linter instead of repeating it, names the merge gate and why, and states the one ViewModel/UIKit rule an agent (and a couple of humans) had actually gotten wrong before. The short file is the harder one to write, it forces you to decide what actually matters instead of writing down everything you know.&lt;/p&gt;

&lt;p&gt;This is the same standardize-the-few-things-that-compound instinct behind &lt;a href="https://veheria.tech/blog/modularizing-legacy-ios-app/" rel="noopener noreferrer"&gt;modularizing a legacy iOS app without stopping delivery&lt;/a&gt;: legislate the few rules that matter across the whole team, leave the rest to local judgment. And it only holds if the codebase backs it up. A CLAUDE.md pointing at "the linter enforces this" is only as good as that linter config being current and actually run in CI.&lt;/p&gt;

&lt;p&gt;What's the longest-standing rule in your own CLAUDE.md that you're not sure is still true?&lt;/p&gt;

&lt;p&gt;If you're standing up this workflow on an iOS team and want a second pair of eyes on what belongs in the file versus what's just noise, &lt;a href="https://veheria.tech/work/" rel="noopener noreferrer"&gt;that's the kind of thing I help with&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://veheria.tech/blog/claude-md-for-ios-teams/" rel="noopener noreferrer"&gt;veheria.tech/blog/claude-md-for-ios-teams&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>claudecode</category>
      <category>ai</category>
      <category>swift</category>
    </item>
    <item>
      <title>SwiftUI vs UIKit in 2026: A Staff Engineer's Decision Framework</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Fri, 04 Sep 2026 09:03:41 +0000</pubDate>
      <link>https://dev.to/5uper0/swiftui-vs-uikit-in-2026-a-staff-engineers-decision-framework-h4p</link>
      <guid>https://dev.to/5uper0/swiftui-vs-uikit-in-2026-a-staff-engineers-decision-framework-h4p</guid>
      <description>&lt;p&gt;Every SwiftUI-vs-UIKit take argues which framework is better. That's the wrong question. The one that actually matters: which one can this specific team ship and maintain, on this specific timeline, without the codebase becoming the bottleneck. Framework superiority is a debate for a blog post. Team fluency and timeline are what actually decide a ship date.&lt;/p&gt;

&lt;h2&gt;
  
  
  Team fluency beats framework features
&lt;/h2&gt;

&lt;p&gt;An experienced UIKit team moving to SwiftUI pays a real productivity cost during ramp-up, even on the exact greenfield work SwiftUI is theoretically best at. The framework being technically superior for a use case doesn't matter if the team writing it is slower in it for the next two quarters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decide per screen, not per app
&lt;/h2&gt;

&lt;p&gt;The better unit of decision isn't the app, it's the screen. Complex animation work and legacy SDK integrations still favor UIKit. Forms and straightforward navigation favor SwiftUI. Forcing one framework across an entire app because it won the debate once is how you end up fighting the wrong tool on the one screen that needed the other one.&lt;/p&gt;

&lt;h2&gt;
  
  
  What breaks in year two, not year one
&lt;/h2&gt;

&lt;p&gt;A screen that started as a simple form can grow custom interaction requirements a year later that the original framework choice never anticipated. The failure mode isn't picking wrong on day one, it's not revisiting the choice as a screen's requirements change underneath it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hiring cost nobody prices in
&lt;/h2&gt;

&lt;p&gt;Junior engineers ramp on SwiftUI faster. Senior UIKit engineers take longer to become productive in SwiftUI than the migration timeline usually assumes. If your hiring plan and your framework plan aren't the same conversation, one of them is wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing isn't a rounding error
&lt;/h2&gt;

&lt;p&gt;SwiftUI testing looks different enough from UIKit testing that a team can't assume the skill transfers by osmosis. That's ramp-up time you have to plan for explicitly, the same way you'd plan for a new build tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  The framework, applied
&lt;/h2&gt;

&lt;p&gt;Four situations, four different calls: a greenfield project with an experienced team defaults to SwiftUI. A stable, working UIKit codebase doesn't get rewritten for novelty. An active migration needs its dual-stack interim budgeted as its own tracked phase with a real exit criterion, not folded into "get to the target architecture" and hoped to resolve itself, the same underestimation shows up in &lt;a href="https://veheria.tech/blog/modularizing-legacy-ios-app/" rel="noopener noreferrer"&gt;modularizing a legacy iOS app without stopping delivery&lt;/a&gt;, where the interim ran months longer than planned for exactly this reason. And any individual screen gets evaluated on its own requirements, not on which framework the rest of the app happens to use.&lt;/p&gt;

&lt;p&gt;If you're walking into this decision cold: don't start with the framework. Start with your team's fluency, your timeline, and which screens actually need what. The framework comparison is the easy 20% of the decision. The other 80% is admitting your team and your timeline are what's actually being decided, not React-Native-style feature checklists.&lt;/p&gt;

&lt;p&gt;If you're staring at this decision on a real team with a real deadline and want a second opinion before committing, that's what I help with in a &lt;a href="https://veheria.tech/work/" rel="noopener noreferrer"&gt;strategy session&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What's the one screen in your app where you'd pick the other framework if you were starting it today?&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://veheria.tech/blog/swiftui-vs-uikit-2026/" rel="noopener noreferrer"&gt;veheria.tech/blog/swiftui-vs-uikit-2026&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>swift</category>
      <category>swiftui</category>
      <category>engineering</category>
    </item>
    <item>
      <title>llms.txt Implementation: The Part Nobody Measures</title>
      <dc:creator>Oleh Veheria</dc:creator>
      <pubDate>Mon, 24 Aug 2026 07:00:05 +0000</pubDate>
      <link>https://dev.to/5uper0/llmstxt-implementation-the-part-nobody-measures-2144</link>
      <guid>https://dev.to/5uper0/llmstxt-implementation-the-part-nobody-measures-2144</guid>
      <description>&lt;p&gt;My robots.txt has a line that says AI search and citation crawlers are "explicitly welcomed." I wrote that in July, four months after I'd already shipped an &lt;code&gt;llms.txt&lt;/code&gt; file to this exact site. In that time I have not been able to confirm that a single one of those crawlers has ever opened it.&lt;/p&gt;

&lt;p&gt;That is not the story you get from most llms.txt guides. Search "llms.txt implementation" and you get a dozen "Complete 2026 Guide" posts explaining the syntax, telling you to keep it to 20-50 curated links instead of dumping your sitemap, and listing which companies now publish one. All correct. All missing the part that actually matters once you have shipped it: how do you know it did anything?&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually shipped, and when
&lt;/h2&gt;

&lt;p&gt;I added &lt;code&gt;llms.txt&lt;/code&gt; to veheria.tech back in March, before I had more than two blog posts to point at (PR #63). It sat there as a curated summary: who I am, what I do, how to reach me. In July, once the AI-native engineering wedge posts started shipping, I updated it to list them explicitly (PR #84), each with a one-line description of what the post actually covers, not just a URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Writing&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Claude Code for iOS Development: The Workflow, Not the Setup&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://veheria.tech/blog/claude-code-ios-development/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;: where an AI agent is trusted in a real iOS team's loop, and where a human keeps the call.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;A Claude Code Review Workflow That Saved 30 Minutes Per Engineer a Day&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://veheria.tech/blog/claude-code-code-review-workflow/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;: what to automate, what to keep human, and the one number measured after months of daily use.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three posts, not twenty sitemap URLs. That was a deliberate call, not laziness. It is the same rule I run my code-review agents on: &lt;a href="https://veheria.tech/blog/claude-code-code-review-workflow/" rel="noopener noreferrer"&gt;every finding has to cite a file, a line, and a concrete failure scenario, or it gets dropped&lt;/a&gt;. A link with no reason for a model to follow it is noise, whether it comes from an agent's review comment or from a sitemap dump into a file that is supposed to be curated. The entire pitch of llms.txt over a sitemap is that a human decided what matters. Paste the sitemap in and you have thrown that advantage away to save five minutes.&lt;/p&gt;

&lt;p&gt;I left more out than I put in. The full site has language variants in English, Spanish, and Ukrainian; only the English canonical URLs made the file, because an assistant summarizing my work does not need three copies of the same claim. It has a contact page, a work page, and an about page; only &lt;code&gt;/work&lt;/code&gt; earned a line, because that is the one page where the outcome of reading this file (someone reaching out) actually happens, and a model deciding whether to surface me is more useful with one clear next step than three competing ones. Every entry I kept had to answer "what does a model do with this that it could not do with the URL alone," the same test I apply to a code comment before I let it survive review. Most links fail that test. That is exactly why most llms.txt files, mine included at first draft, start too long and get cut, not the other way around.&lt;/p&gt;

&lt;h2&gt;
  
  
  The measurement problem nobody in the guides admits
&lt;/h2&gt;

&lt;p&gt;Here is where it gets uncomfortable. I already run SEO on this site the way I run everything else here: headless, through scripts that pull Google Search Console and GA4 on a schedule. That pipeline can tell me, to the click, when a page gets indexed and what query it shows up for. It cannot tell me whether GPTBot, ClaudeBot, or PerplexityBot ever fetched &lt;code&gt;/llms.txt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The reasons are structural, not a gap in my scripts. GA4 fires on JavaScript execution in a browser; a crawler doing a raw HTTP fetch of a static Markdown file never runs a line of JS, so it never reports. Cloudflare Pages, on the free tier this site runs on, does not expose raw request logs, only aggregate analytics that do not break out user agents at the path level. The companies the guides cite as proof llms.txt "works" (Anthropic, Stripe, Vercel, Cloudflare) all run their own infrastructure with real access logs. A solo site on a hosting tier built for cheap static delivery does not get that visibility for free.&lt;/p&gt;

&lt;p&gt;So the honest state of my &lt;code&gt;llms.txt&lt;/code&gt;, four months in, is: it costs nothing, it might be read, and I have no instrument that would tell me either way. Before writing this I checked the other properties I run content or SEO for, not just this one. Most of them already ship an &lt;code&gt;llms.txt&lt;/code&gt;. None of them, this site included, has any way to confirm a crawler opened one. Every guide I found treats adoption as the finish line. Adoption is the easy 90% of the work. The other 10%, knowing if it did anything, is the part that would actually justify spending more time on it, and nowhere in what I run had anyone, including me until an hour ago, gotten past the first 90%.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mistake, and what I'd do differently
&lt;/h2&gt;

&lt;p&gt;I have made this exact mistake before, on a bigger stack. When I put Claude Code agents into a multinational iOS team's review loop, I deployed first and picked the metric of record after, which meant the first stretch of tuning was against a feeling instead of a number. &lt;code&gt;llms.txt&lt;/code&gt; is the same failure in miniature: I shipped the artifact and treated "it's live" as the win condition, without deciding up front how I would ever know if it earned its keep.&lt;/p&gt;

&lt;p&gt;What I'd do differently is treat instrumentation as part of the ship, not a follow-up. Search Console will not help here; it reports on Googlebot's own crawl, not on GPTBot, ClaudeBot, or PerplexityBot fetching a static file. The version I actually plan to try next: a Cloudflare Pages Function in front of the &lt;code&gt;/llms.txt&lt;/code&gt; route that logs the User-Agent header on every request before serving the file. Cheap to build, and it is the difference between "I hope a crawler reads this" and a line in a log that says one did. I did not build that when I shipped the file in March, or when I updated it in July. That is the mistake, not the file itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should you still ship it
&lt;/h2&gt;

&lt;p&gt;Yes, and the guides are right about that much. Adoption cost is minutes, the downside is zero, and being the entry that shows up when an assistant is asked to summarize your site is worth having even if you cannot yet prove the mechanism. What I'd change about how everyone, myself included, talks about it: stop writing as if shipping the file were the result. It is the setup. The result is whatever you can actually verify happened after, and right now, for anyone without an enterprise logging stack, that verification does not exist by default. Say that part out loud instead of implying the file is doing invisible work you cannot see.&lt;/p&gt;

&lt;p&gt;This is the same judgment call that runs through most of what I write about &lt;a href="https://veheria.tech/blog/ai-agents-engineering-team-workflow/" rel="noopener noreferrer"&gt;putting AI agents into a real engineering workflow&lt;/a&gt;: the interesting question is never whether the tool is worth adopting, it almost always is. The interesting question is whether you built a way to tell if it is working, before you started telling other people to adopt it too.&lt;/p&gt;

&lt;p&gt;If you are deciding where to spend engineering time on AI-visibility work versus everything else competing for the sprint, that kind of "does this actually move something, or is it cargo cult" call is exactly what &lt;a href="https://veheria.tech/work/" rel="noopener noreferrer"&gt;I help teams work through in a strategy session&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you have shipped &lt;code&gt;llms.txt&lt;/code&gt; on your own site, have you found any way to confirm a crawler actually read it? I would like to know I am not the only one flying blind on this.&lt;/p&gt;




&lt;p&gt;Originally published at &lt;a href="https://veheria.tech/blog/llms-txt-implementation/" rel="noopener noreferrer"&gt;veheria.tech/blog/llms-txt-implementation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>ai</category>
      <category>webdev</category>
      <category>analytics</category>
    </item>
  </channel>
</rss>
