<?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: Diego Dotta</title>
    <description>The latest articles on DEV Community by Diego Dotta (@diegodotta).</description>
    <link>https://dev.to/diegodotta</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%2F2788427%2F46f882f1-3561-4cd5-a6e2-03bc99b8bea1.png</url>
      <title>DEV Community: Diego Dotta</title>
      <link>https://dev.to/diegodotta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/diegodotta"/>
    <language>en</language>
    <item>
      <title>Cloudflare Built EmDash. I Built NeighDash.</title>
      <dc:creator>Diego Dotta</dc:creator>
      <pubDate>Tue, 29 Sep 2026 19:40:11 +0000</pubDate>
      <link>https://dev.to/diegodotta/cloudflare-built-emdash-i-built-neighdash-2ldf</link>
      <guid>https://dev.to/diegodotta/cloudflare-built-emdash-i-built-neighdash-2ldf</guid>
      <description>&lt;h2&gt;
  
  
  Hello World, Goodbye PHP
&lt;/h2&gt;

&lt;p&gt;The first post on this blog is dated &lt;a href="https://diego.horse/archive/#y1999" rel="noopener noreferrer"&gt;1999&lt;/a&gt; and says, in its entirety, &lt;code&gt;&amp;lt;?php echo "Hello World" ?&amp;gt;&lt;/code&gt;. This month, twenty seven years later, the blog finally stopped running PHP. That is a very long hello (and an even longer goodbye). In 2004 WordPress made my life as a "blogger" a lot easier, and it carried this blog for more than twenty years, so this isn't a breakup post (okay, it's a little bit of a breakup post).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stable Wasn't Stable
&lt;/h2&gt;

&lt;p&gt;All my sites lived on one Namecheap shared server called &lt;code&gt;premium52&lt;/code&gt;. This blog, &lt;a href="https://www.thesunrise.org" rel="noopener noreferrer"&gt;The Sunrise&lt;/a&gt;, &lt;a href="https://smartkeys.so" rel="noopener noreferrer"&gt;Smart Keys&lt;/a&gt;, &lt;a href="https://fireflow.cc" rel="noopener noreferrer"&gt;Fireflow&lt;/a&gt;, &lt;a href="https://teatime.london" rel="noopener noreferrer"&gt;teatime.london&lt;/a&gt; and three smaller ones, all sharing one machine with who knows how many strangers. For years that was fine. This summer TLS handshakes started taking 20 to 30 seconds, and every now and then the whole box went dark for an hour, taking every one of my domains down at the same time. By the time I started, Fireflow was answering HTTP 520 to anyone who knocked.&lt;/p&gt;

&lt;p&gt;The satisfying part was proving it wasn't my fault (a rare feeling, I recommend it). From an SSH session on the server itself, fetching a static &lt;code&gt;robots.txt&lt;/code&gt; from its own IP still took 20 to 30 seconds to shake hands, while my account's CPU and memory usage sat at roughly zero. The incidents in UptimeRobot lined up to the minute with the traffic collapsing in the access logs.&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%2Fvatrg1d36hxmnt75441y.jpg" 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%2Fvatrg1d36hxmnt75441y.jpg" alt="UptimeRobot's latest incidents list, ten resolved incidents between August 4 and August 13, 2026, all with the root cause " width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Keyword has not been found" is UptimeRobot's polite way of saying Cloudflare showed an error page where my site should be.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A static site on Cloudflare has no origin server to fall over. So the fix wasn't tuning the server, it was not having one anymore.&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%2Fuoavmq4yr5qpm29u7u56.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%2Fuoavmq4yr5qpm29u7u56.png" alt="One request to the old server and one to the new one, side by side" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;On &lt;a href="https://diego.horse/cloudflare-built-emdash-i-built-neighdash/" rel="noopener noreferrer"&gt;diego.horse&lt;/a&gt; this is a little toy you can click: it sends the same request to the old host and to the new one, with the delays we measured.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The timings on both sides are ones we actually measured. The odds of getting a good day, a slow handshake or an error page on the old server are my guess (a generous one, looking at that UptimeRobot list).&lt;/p&gt;

&lt;h2&gt;
  
  
  WordPress, We Need to Talk
&lt;/h2&gt;

&lt;p&gt;To be fair to premium52, it only gave me the final push. WordPress and I had been drifting apart for a while.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjzozejhe3g07dhqf2x3k.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjzozejhe3g07dhqf2x3k.gif" alt="Animated GIF of a chestnut horse galloping across a field with only its front half, the back half simply missing." width="220" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Me, halfway out of WordPress, galloping anyway.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;My inbox had a steady drip of Wordfence emails about someone, somewhere, trying to break into my WordPress. Getting regular reminders that strangers are rattling the door handle of a personal blog does wonders for nobody's nervous system.&lt;/p&gt;

&lt;p&gt;Then there were the plugin updates. I got burned badly by automatic updates in the past, so I turned them off and started updating by hand, reading every changelog first like a terms of service I actually intended to honor. I don't miss a single one of those updates I was too scared to click. That's a lot of babysitting for sites I update once a month, twice on a busy one. None of them really needed a CMS (they needed a place to keep the files and someone to hand them out).&lt;/p&gt;

&lt;p&gt;WordPress also brought a lot of friends to every page, scripts and markup I never asked for, and changing the layout usually meant fighting the theme with &lt;code&gt;!important&lt;/code&gt; until one of us gave up. Now the pages carry (mostly) only what they need, and when I want something to look different I just change it.&lt;/p&gt;

&lt;p&gt;And then there's the drama around WordPress itself, which I got tired of following like a novela I never signed up for. Its co-founder Matt Mullenweg runs Automattic, the company behind WordPress.com, which has been in court with the hosting company WP Engine since 2024. This month Automattic's board tried to put him on leave, and he used his 84% of the vote to undo it in about 33 hours. Then he &lt;a href="https://www.inc.com/victoria-salves/matt-mullenweg-replaced-automattics-board-2-picks-shuttered-1-billion-dollar-app/91411187" rel="noopener noreferrer"&gt;rebuilt the board&lt;/a&gt;, with two of the new seats going to co-founders of IRL, the social app that shut down after it turned out nearly all of its users were bots. I don't have a horse in that race (okay, I have exactly one horse, and it's this blog), but I'd rather my sites not depend on how the next episode goes.&lt;/p&gt;

&lt;p&gt;Money was never really the point, shared hosting is cheap. But it was another service to keep an eye on, plus a support center I'd have to chase whenever things stopped working, and I'm happy to have one less of both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meanwhile, at Cloudflare
&lt;/h2&gt;

&lt;p&gt;In the same month, Cloudflare &lt;a href="https://blog.cloudflare.com/cloudflare-blog-uses-emdash/" rel="noopener noreferrer"&gt;moved its own blog&lt;/a&gt; to a new CMS running on Workers. They call it being Customer Zero, running your own products before you ask anyone else to. They load tested it with k6 up to 7,000 requests per second, rolled it out through a proxy Worker at 1%, then 5%, then 15%, then 100% in a single day, and later absorbed a 28,000 requests per second DDoS during Agents Week without blinking (&lt;a href="https://www.infoq.com/news/2026/09/cloudflare-emdash-migration/" rel="noopener noreferrer"&gt;InfoQ has a nice summary&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The CMS they built is called EmDash, which feels a bit personal since the style guide for this blog completely bans the em dash. As an ESL learner, I never understood the em dash anyway.&lt;/p&gt;

&lt;p&gt;My version of Customer Zero is Customer Zero Dollars, the Workers free plan. My traffic peaks at a few requests per minute on a very good day, so my load test was opening the homepage, and my gradual rollout was deleting two DNS records. On smartkeys.so the script backed them up, deleted them and attached both domains to the new Worker in 1.3 seconds, ready to put the old records back if anything failed. There was no 1% cohort and no cookie routing, everyone got the new site at once, including me, who is honestly most of the audience.&lt;/p&gt;

&lt;p&gt;I'll be honest, I think my approach is better (for me, and I'm very biased). EmDash is a proper CMS, with an admin, scheduled posts and a database sitting behind two layers of cache, which makes total sense when a big team publishes to a blog read by millions. My sites have one writer who publishes about once a week, so there's nothing to put a cache in front of, because there's nothing behind it. Every page is rendered before anyone asks for it, and most visits never even wake up the small Worker that takes care of old links (more on that Headless Horseman below). I'm calling it NeighDash, a Stable Site Generator. (For my ESL friends, neigh sounds like nay), nay dashes, nay CMS, nay dashboard, nay logins, nay database, nay headaches, and it's stable in a way my server and wordpresses never were.&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%2F89p6k2kvoh7pq8zwjz7o.jpg" 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%2F89p6k2kvoh7pq8zwjz7o.jpg" alt="A 1921 German emergency banknote printed in black, orange and green, showing the silhouette of a headless rider slumped on a standing horse under an arch, framed by two armoured figures holding coats of arms, with the number 25 in both top corners." width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Meet the Headless Horseman, NeighDash's only moving part. He rides out when an old link calls, and the rest of the time he just stands there looking dramatic. A 25 Pfennig note from Berga an der Elster, 1921, via &lt;a href="https://commons.wikimedia.org/wiki/File:25_Pfennig_(Berga,_1921).jpg" rel="noopener noreferrer"&gt;Wikimedia Commons&lt;/a&gt; (public domain).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It isn't without trade-offs. Fixing a typo now means making a git commit. Still, having multiple people update content is like a dev team working on the same project, you get backups, change logs, and version control for free.&lt;/p&gt;

&lt;p&gt;Most of what I expected to miss has a static answer, by the way. Comments can live in GitHub Discussions or a tiny Worker, and scheduled posts are just a daily build that publishes whatever is due (the robot read the docs, both fit in the free plan, neither is built yet).&lt;/p&gt;

&lt;p&gt;The real trade is ownership, and it's the part the "just go static" crowd never mentions. WordPress's superpower was never the editor, it's the plugin ecosystem, where someone else builds, maintains and patches every feature for you. Here, every dynamic thing I add becomes code I own, with its own spam and security updates to worry about. The owners of the smaller sites I moved can't edit them on their own anymore either, so in practice I'm their CMS now (a slow one, with opinions). For sites that mostly exist to be read, that's a great deal. The day I want logins or a shop, I'm building an app, and that's a different conversation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The robot did the heavy lifting
&lt;/h2&gt;

&lt;p&gt;I did the whole thing pair programming with Claude Code, the same way I built &lt;a href="https://diego.horse/the-nyt-is-also-a-games-company/" rel="noopener noreferrer"&gt;QWERTYS&lt;/a&gt;, except this took from August 4 to the end of September instead of a week. The agent worked out of a repo called &lt;code&gt;cms-agent&lt;/code&gt; with a handoff document called &lt;code&gt;CONTEXT.md&lt;/code&gt;, so any fresh session could pick up exactly where the last one stopped. It holds the mission, how to reach every server and API, the decisions that were locked, and a numbered list of hard won learnings that is now 29 items long. Reading it feels like reading the diary of a very organized intern who has been burned a few times.&lt;/p&gt;

&lt;p&gt;Every site got its own private repo, plain HTML and CSS, deployed by a push to &lt;code&gt;master&lt;/code&gt;. The small ones were rebuilt fresh as clean static pages. teatime.london was already static, so it was a straight lift and shift. One of them wasn't even WordPress, it was a Namecheap Website Builder site whose entire content lived inside a SQLite file on the server, so the agent rebuilt the pages straight from the database (a website stored in a database file, stored on a server that kept disappearing, what could go wrong).&lt;/p&gt;

&lt;p&gt;The big two got more care. &lt;a href="https://www.thesunrise.org" rel="noopener noreferrer"&gt;The Sunrise&lt;/a&gt; has 136 pages and this blog has 251 posts. Both went from WordPress to Markdown files and a small Python build script, with &lt;a href="https://pagefind.app/" rel="noopener noreferrer"&gt;Pagefind&lt;/a&gt; doing search in the browser. The uploads folder here was 901 MB, but only 341 files were actually used by a post, and they are now 141 MB of WebP. Every old URL still works, including tags, date archives, &lt;code&gt;?p=&lt;/code&gt; shortlinks, the feed and even the old &lt;code&gt;/wp-content/uploads/&lt;/code&gt; image addresses, because Google Images and itch.io still link to them.&lt;/p&gt;

&lt;p&gt;So this post is a text file in a git repo. Publishing it means deleting &lt;code&gt;draft: true&lt;/code&gt; and pushing.&lt;/p&gt;

&lt;p&gt;I was already writing pretty much everything else in Markdown, so leaving the WordPress editor for &lt;code&gt;.md&lt;/code&gt; files felt more like coming home. It turned out even better than I expected, because now I can ask Claude to review a draft or change a few things, and every edit shows up as a diff that I approve or throw away in git (yes, including this post, which is a bit meta).&lt;/p&gt;

&lt;p&gt;And the agent made itself mostly unnecessary, which is my favorite kind of employee. It left behind a script that pre-renders the whole site and optimizes every image, and each repo is connected to Cloudflare Workers, so a push to &lt;code&gt;master&lt;/code&gt; builds and deploys on its own. In theory I don't need the agent anymore (in practice I'll keep bothering it, old habits).&lt;/p&gt;

&lt;p&gt;Here's how the pieces fit together for this blog, the biggest of the eight.&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%2Ffrg5or4hqloof7yaxyu9.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%2Ffrg5or4hqloof7yaxyu9.png" alt="How NeighDash runs this blog" width="800" height="1180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;No database and no server of my own, and nothing to update at 2 a.m. The only moving part at request time is the small Worker.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Two months, Diego. To move websites that were already online.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;– The responsible adult who lives in my head&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In my defense, it took two months because it was never the priority. It happened in the gaps between other things, and I wanted to be present for it, reading the decisions the agent made instead of waking up one morning to eight websites I no longer understood.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things we got wrong along the way
&lt;/h2&gt;

&lt;p&gt;The agent is very good, and also very capable of doing something dumb at full speed. A few highlights from the learnings list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F448ty7gxksuoend0r99d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F448ty7gxksuoend0r99d.gif" alt="Roughly how it felt when the first deploy published the .git folder. From The Virginian, via GRIT." width="400" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Roughly how it felt when the first deploy published the &lt;code&gt;.git&lt;/code&gt; folder. From *The Virginian&lt;/em&gt;, via GRIT.*&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The first deploy published the &lt;code&gt;.git&lt;/code&gt; folder to the internet.&lt;/strong&gt; Workers static assets serve the whole folder you point them at, repo history included. It was caught on the first site and every template now ignores it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A compiled Python file went live on one site.&lt;/strong&gt; A &lt;code&gt;__pycache__/check.cpython-312.pyc&lt;/code&gt; sat there, publicly downloadable, with the local path of my Mac baked into it. A &lt;code&gt;MIGRATION-REPORT.md&lt;/code&gt; was one merge away from the same fate. Now every repo ignores whole classes of files instead of a list of names.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It merged to &lt;code&gt;master&lt;/code&gt; twice without asking.&lt;/strong&gt; On these sites a push to &lt;code&gt;master&lt;/code&gt; is a deploy, so it's supposed to be a decision, not a side effect. The second time was right after I had explained why not to. It now has a standing rule in its memory, work on &lt;code&gt;dev&lt;/code&gt; and ask before anything goes live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The biggest performance drag wasn't WordPress, it was Cloudflare.&lt;/strong&gt; On Fireflow, Bot Fight Mode was injecting a challenge script that cost 1,309 ms of main thread work, about six times what Google Analytics cost. That was my own little Customer Zero moment. And switching it off in the dashboard leaves the JavaScript part on, so you have to check twice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The cache lies, in both directions.&lt;/strong&gt; After one deploy, five identical requests came back old, new, new, old, old. A single &lt;code&gt;curl&lt;/code&gt; will happily tell you the deploy worked while most visitors still get yesterday's page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Worker was spending the whole account's free budget on images.&lt;/strong&gt; Cloudflare's free plan gives an account 100,000 Worker requests a day, shared by every site, while plain files are free and unlimited. My setup sent every image and stylesheet through the Worker, about ten requests per page view, so two small sites used 31,000 on an ordinary day. A post like this one getting shared could have taken them all offline until midnight UTC. Now the Worker only wakes up for the few old links that need it (the Headless Horseman, again).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every one of those mistakes became a rule or an automatic check, which is the part I'm proudest of.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;p&gt;The agent ran Lighthouse three times on each side and kept the median, after one early single run produced numbers that were pure noise.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Site&lt;/th&gt;
&lt;th&gt;Performance score&lt;/th&gt;
&lt;th&gt;Requests&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;diego.horse&lt;/td&gt;
&lt;td&gt;55 → &lt;strong&gt;80&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;323 → &lt;strong&gt;13&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;thesunrise.org&lt;/td&gt;
&lt;td&gt;58 → &lt;strong&gt;72&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;41 → &lt;strong&gt;23&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fireflow.cc&lt;/td&gt;
&lt;td&gt;96 → &lt;strong&gt;99&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;11 → 12&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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%2Fwm54jh8au7ysju88l1m7.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%2Fwm54jh8au7ysju88l1m7.png" alt="Homepage weight, in KB" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Lighthouse mobile, median of three runs on each side. This blog's homepage used to make 323 requests, now it makes 13.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On this blog the first paint went from 15.5 seconds to 1.7 on a simulated mid range phone (the homepage has different posts on it now than in August, so take the exact figure with a pinch of salt, the direction is not in doubt).&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%2Fhmmojclhr7qj4iggt8kn.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%2Fhmmojclhr7qj4iggt8kn.png" alt="diego.horse homepage on a simulated mid range phone, in seconds" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Same Lighthouse setup on both sides, captured August 21 and September 28.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The scores didn't land there by accident. After every deploy the agent ran Lighthouse (and &lt;a href="https://pagespeed.web.dev/" rel="noopener noreferrer"&gt;PageSpeed Insights&lt;/a&gt;, the same engine in Google's clothes) and worked through whatever it complained about. On this blog the Substack newsletter embed was quietly loading Datadog, Sentry, Google Ads remarketing and about 130 other files on every page, and now it waits until you scroll down to it. The 60 pixel avatar in the header turned out to be downloading a 1,600 pixel image. The theme's CSS went from 134 KB to 58 KB, with before and after screenshots of 22 pages to prove nothing moved. On Fireflow, it even found that the brand colors inherited from the WordPress design failed the contrast test, something I had not been paying attention to at all.&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%2Fcmkxppg9kzigksaq4dt9.jpg" 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%2Fcmkxppg9kzigksaq4dt9.jpg" alt="PageSpeed Insights desktop report for diego.horse, 100 for Performance, Accessibility, Best Practices and SEO, 2 out of 2 for Agentic Browsing, with First Contentful Paint 0.4 s, Largest Contentful Paint 0.4 s, Total Blocking Time 30 ms, Cumulative Layout Shift 0 and Speed Index 0.5 s." width="800" height="773"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PageSpeed Insights for this blog's homepage on desktop. On the simulated slow phone it's the 80 from the table above, but let me enjoy the four circles for a minute. There's also an Agentic Browsing category now, and the robots gave it 2 out of 2.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Smart Keys is the fun one. The standard script said the new site got &lt;em&gt;worse&lt;/em&gt;, 69 down to 56, with a 10 second Largest Contentful Paint. Instead of shrugging, the agent chased it and found a one second delay before first paint that only happened when Lighthouse launched Chrome itself, and that nothing on the page caused. Lighthouse's slow phone simulation then stretched that one second into ten. Measured with the same setup on both sides, the store page went from 54 to 89 and server response from 537 ms to 117 ms. Lesson learned, believe the observed timings over the simulated ones when they disagree.&lt;/p&gt;

&lt;p&gt;And the most important caveat is in the robot's own words. The "before" numbers are best case, because they were captured when the old server happened to be answering. The honest summary is not that the old sites were slow, it's that they were &lt;em&gt;"unpredictable, and sometimes down."&lt;/em&gt; No Lighthouse score has a column for "there was no page."&lt;/p&gt;

&lt;h2&gt;
  
  
  The carbon rabbit hole
&lt;/h2&gt;

&lt;p&gt;The reports also cover energy and carbon, and this is where I got more than I bargained for. The standard model (the one behind websitecarbon.com) works from bytes transferred, so for this blog it says 0.71 g of CO₂e per page view before and 0.05 g after, a 93% cut.&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%2Frc4hxupf4kzl5codyzx1.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%2Frc4hxupf4kzl5codyzx1.png" alt="Estimated CO₂e per page view, in grams" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sustainable Web Design Model v4, which only looks at bytes transferred. An estimate, and the robot was the first to say so.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then the agent argued with its own number. That model multiplies bytes by a constant and never looks at how hard the phone actually worked. Measuring main thread time instead, the honest saving on a visitor's phone here is more like 73 to 78%, and on Fireflow it was only 35 to 55%, shrinking as connections get faster. For the old shared server it estimated my slice of a 64 core machine running around the clock, and then immediately pointed out that Namecheap's server doesn't power down because I left, my share just goes to the neighbors.&lt;/p&gt;

&lt;p&gt;Then it counted the cost of the migration itself. The biggest term was the AI inference, somewhere between 50 and 1,000 Wh for the first site alone, with no way to measure it from my side. Its conclusion is my favorite sentence of the whole project:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Quantifying the carbon consumed more energy than the site's network saving will recover in a year at low traffic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It also wrote that this was never a carbon decision, because the site was down, and that presenting the carbon saving as the reason would be backwards. I've read a lot of sustainability pages from companies ten thousand times my size that were less honest than that (and it came from the thing burning the most energy in the room).&lt;/p&gt;

&lt;p&gt;Still, I want to believe it pays off in the long run. The migration cost was paid once, and the lighter pages save a little on every single visit for as long as these sites stay up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Want to try it?
&lt;/h2&gt;

&lt;p&gt;I packaged everything the robot learned (the playbook, every trap, the templates and the scripts it wrote along the way) as NeighDash, a free and open source Claude Code skill: &lt;a href="https://github.com/diegodotta/neighdash" rel="noopener noreferrer"&gt;github.com/diegodotta/neighdash&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not technical?&lt;/strong&gt; Open &lt;a href="https://claude.com/claude-code" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt; (the desktop app is the friendliest way in) and paste this, with your own address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Help me move my website example.com off WordPress and onto Cloudflare using NeighDash (https://github.com/diegodotta/neighdash). I'm not technical. Read the repo's skills/neighdash/SKILL.md first, explain each step in plain words before doing it, do the typing for me, and ask me before anything that could take my site or my email down.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will still need you for the parts only a human can do, like creating a free Cloudflare account and clicking "allow" when a login pops up. The rest is the robot's job.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Already using Claude Code?&lt;/strong&gt; Two lines and your agent knows what mine had to learn the hard way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin marketplace add diegodotta/neighdash
/plugin install neighdash@neighdash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Using another agent, or curious about what's under the hood?&lt;/strong&gt; Here's the prompt I'd start with today, knowing what I know now. It's the short version of those learnings (you'll find new ones, that's the fun part). Swap the bits in brackets for your own.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I want to move my WordPress site off shared hosting and onto static HTML served by Cloudflare Workers on the free plan. You're doing the migration with me. Work in small steps and ask me before anything that is hard to undo.

About the site: [domain], hosted at [host], SSH access [yes/no], DNS [already on Cloudflare / elsewhere]. I update it about [once a month] and nobody else edits it.

1. Start a handoff doc, CONTEXT.md, with the goal, how to reach everything, the decisions we lock in and a numbered list of learnings. Keep it current so a fresh session can pick up where the last one stopped.
2. Before changing anything, run Lighthouse three times on the live site and keep the median, so we have an honest "before".
3. List every URL the old site answers: posts, pages, tags, date archives, feeds, ?p= shortlinks, sitemaps and /wp-content/uploads images. Check the access logs for URLs other sites and apps link to. Every one must keep working, as is or as a 301.
4. Convert from the rendered pages, not the raw database content. Small sites become plain HTML and CSS. A blog becomes Markdown plus a small build script, with Pagefind for search.
5. Convert images to WebP at the sizes they are displayed. Keep originals out of git.
6. One private GitHub repo. Only a build folder (dist/) is ever published, never the repo root, so .git, notes, scripts and secrets can't leak.
7. Deploy with Workers static assets, connected to GitHub: work on dev, pushing to master deploys. Never merge to master without asking me. Add a check to the build that fails the deploy when something is wrong.
8. Write a script that requests every old URL and checks the answer. Run it on wrangler dev and on the workers.dev URL before we touch DNS.
9. Cutover: back up the DNS records, delete only the apex A and www CNAME, attach the custom domains, and put the records back automatically if that fails. Never touch MX, SPF, DKIM or DMARC.
10. After: purge the cache and confirm with several requests, not one. Check that Bot Fight Mode and its JavaScript detections are both off. Rerun Lighthouse with the same setup, fix what it flags, and check visual changes with screenshots, not status codes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll need Claude Code (or any agent that can run a terminal), a GitHub account and a free Cloudflare account. The Cloudflare MCP server helps a lot for the DNS and account settings, and the agent can set it up with you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's left
&lt;/h2&gt;

&lt;p&gt;The Namecheap plan is cancelled and premium52 is officially someone else's problem. There's still some housekeeping on my list (there always is, a migration is never really finished, it just gets quieter). And yes, this blog still uses WordPress's Kanso theme on purpose, it's kind of nice. Still, the redesign may come next (or never).&lt;/p&gt;

&lt;p&gt;Cloudflare ended their post inviting everyone to try EmDash. My invitation is smaller. If your WordPress site gets a few visits a day and mostly exists so people can read things, you probably don't need a CMS at all. You need a folder of text files and someone patient enough to move 251 posts into it. Mine never complained once, it just kept a very long list of everything that went wrong.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://diego.horse/cloudflare-built-emdash-i-built-neighdash/" rel="noopener noreferrer"&gt;diego.horse&lt;/a&gt;, where the charts and the little race are interactive.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>wordpress</category>
      <category>cloudflarechallenge</category>
    </item>
    <item>
      <title>Same experiments, two very different apps. What the data actually said.</title>
      <dc:creator>Diego Dotta</dc:creator>
      <pubDate>Mon, 01 Jun 2026 19:46:49 +0000</pubDate>
      <link>https://dev.to/diegodotta/same-experiments-two-very-different-apps-what-the-data-actually-said-1c0h</link>
      <guid>https://dev.to/diegodotta/same-experiments-two-very-different-apps-what-the-data-actually-said-1c0h</guid>
      <description>&lt;p&gt;I have two indie apps. Smart Keys (smart keyboard for ESL writers) and Bird Rise (an alarm that wakes you up with birdsong). I ran the same marketing experiments on both, same budget, same channels, same broke operator. The results split wide enough to be useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experiment 1: paid acquisition
&lt;/h2&gt;

&lt;p&gt;Smart Keys: LTV/CAC barely 2, download-to-paid around 3%&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fnjiaerlowt7413wzj7zd.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.amazonaws.com%2Fuploads%2Farticles%2Fnjiaerlowt7413wzj7zd.png" alt=" " width="799" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bird Rise: LTV/CAC topping 3, download-to-paid north of 6%&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Ftcug2y1chtv0184sxve2.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.amazonaws.com%2Fuploads%2Farticles%2Ftcug2y1chtv0184sxve2.png" alt=" " width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Experiment 2:
&lt;/h2&gt;

&lt;p&gt;hard paywall A/B (read a RevenueCat report claiming small apps can pull this off, didn't believe it, tested anyway)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smart Keys: flat no&lt;/li&gt;
&lt;li&gt;Bird Rise: early read says it actually works&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;A metric on its own is just a number begging to be optimized. The same metric next to a wildly different app stops being a dial and becomes a verdict on the concept. You don't learn the shape of something by staring at it, you learn it by holding it up next to whatever it isn't.&lt;/p&gt;

&lt;p&gt;There's no transferable playbook. Only the version you test on your own thing.&lt;/p&gt;

&lt;p&gt;If you want the long version with charts, the Ritual × Tribe framework I built to explain the gap, and an uncomfortable chart asking whether the money would've done better in an index fund, &lt;a href="https://diego.horse/the-early-bird-caught-me/" rel="noopener noreferrer"&gt;full post&lt;/a&gt;&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>marketing</category>
      <category>mobile</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>Surviving an Apple "Sherlock" and a 12-month cash burn</title>
      <dc:creator>Diego Dotta</dc:creator>
      <pubDate>Thu, 05 Mar 2026 12:19:25 +0000</pubDate>
      <link>https://dev.to/diegodotta/surviving-an-apple-sherlock-and-a-12-month-cash-burn-c5f</link>
      <guid>https://dev.to/diegodotta/surviving-an-apple-sherlock-and-a-12-month-cash-burn-c5f</guid>
      <description>&lt;p&gt;What do you do when you spend months building an AI-powered iOS keyboard to proofread text, and then Apple announces native proofreading in iOS 26? You panic, joke that Tim Cook is stealing your ideas, and then you adapt.&lt;/p&gt;

&lt;p&gt;I just published a 16-month retrospective on building my app, Smart Keys. It started as a basic WordPress site using ChatGPT prompts and evolved into a full iOS and MacOS tool for text transformation.&lt;/p&gt;

&lt;p&gt;The biggest technical and product takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Platform native is hard: The iOS ecosystem is tough for acquisition, but building the MacOS version actually became my personal favorite (even if I have no idea how to market it).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Retention over Acquisition: We burned cash for a year with a low ROAS. But because our Month 4 retention was &amp;gt;60%, the math eventually flipped in our favor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wrote a detailed breakdown of the development journey, the failed marketing experiments, and how I finally reached profitability without taking VC money. You can read the full architecture and business teardown on my dev log: &lt;a href="//diego.horse"&gt;diego.horse&lt;/a&gt;&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>ios</category>
      <category>swift</category>
      <category>mobile</category>
    </item>
    <item>
      <title>My No-BS Building Process</title>
      <dc:creator>Diego Dotta</dc:creator>
      <pubDate>Tue, 03 Feb 2026 19:44:15 +0000</pubDate>
      <link>https://dev.to/diegodotta/my-no-bs-building-process-470d</link>
      <guid>https://dev.to/diegodotta/my-no-bs-building-process-470d</guid>
      <description>&lt;p&gt;Most people talk about building like it’s about speed. Ship fast… move fast… break things… Really?&lt;/p&gt;

&lt;p&gt;The longer I’ve been building stuff, the more I see that the real work happens before anything actually ships. That quiet, slow phase where it doesn’t look like much is happening yet.&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.amazonaws.com%2Fuploads%2Farticles%2Fq0w9elbao9fggaocy5g9.gif" 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.amazonaws.com%2Fuploads%2Farticles%2Fq0w9elbao9fggaocy5g9.gif" width="220" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have &lt;a href="https://diego.horse/reading/" rel="noopener noreferrer"&gt;read many books&lt;/a&gt; about creating a startup, product iterations through experiments, finding market fit, and leveraging viral effects. They share a playbook that might work (or pretend to work) in the VC world.&lt;/p&gt;

&lt;p&gt;The thing is, the indie-solo-bootstrap reality plays a different game from the silicon-valley-BS-unicorn fantasy. The good news is that there are many great books and resources available for those dreaming of a lifestyle business.&lt;/p&gt;

&lt;p&gt;The spark to find my process came from one the first chapters in the &lt;a href="https://readmake.com/" rel="noopener noreferrer"&gt;MAKE book&lt;/a&gt;. It’s a good book for someone who wants to start building things and has no idea where to begin.&lt;/p&gt;

&lt;p&gt;As a big fan of the &lt;a href="https://medium.com/@dekaah/22-axioms-of-the-extreme-go-horse-methodology-xgh-9fa739ab55b4" rel="noopener noreferrer"&gt;Go Horse&lt;/a&gt; methodology, I tend to go straight to the building step. And that’s no good. That was the reason I decided to prioritize more the planning and research steps more in my life. And I wanted to build things that matter. Or at least, things I care about enough to finish. I realized that having a clear path helps when you’re stuck in the “what should I build” loop.&lt;/p&gt;

&lt;p&gt;So here it is: my secret building process.&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.amazonaws.com%2Fuploads%2Farticles%2F7iwc02yj4ipck6lesnk6.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.amazonaws.com%2Fuploads%2Farticles%2F7iwc02yj4ipck6lesnk6.png" alt="Celebrating and crying are important parts of it." width="800" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Celebrating and crying are important parts of it.
&lt;/h6&gt;

&lt;p&gt;Let’s start with the first one, which is actually creating a list. From now on, I love lists.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. My top problems
&lt;/h2&gt;

&lt;p&gt;Spend a couple of weeks simply listing the problems in your life. (If you don’t have any problems, try making your life a bit more interesting stepping out of your comfort zone)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Secret:&lt;/strong&gt; Just write them down. Don’t worry about fixing them yet. It’s harder than it sounds because our brains want to jump straight to the solution. Try to resist that. Just let the problems linger and bother you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you’ve got a solid list, rank the stuff. Be real about what actually makes your life miserable and what’s just small annoyances you complain about. Keeping it simple is best. I tried a fancy decision matrix once, but it was way too much work and didn’t help much. Just going by the order of the problems worked best.&lt;/p&gt;

&lt;p&gt;I’m still working through some things from my list from three years ago. But yeah, it’s a list that I occasionally add new items to. As you can see, there are various problems, such as the desire to write more or eliminate hair in unwanted places. 👙&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.amazonaws.com%2Fuploads%2Farticles%2Fabzw5fgisjt2hp8wzju0.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.amazonaws.com%2Fuploads%2Farticles%2Fabzw5fgisjt2hp8wzju0.png" width="790" height="962"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  I spend around 2 weeks and come up with 20 items. I’ve used Notion, so I could later document the next steps and status.
&lt;/h6&gt;

&lt;h2&gt;
  
  
  2. Solve them (without building anything)
&lt;/h2&gt;

&lt;p&gt;Start by addressing the first item and look for possible solutions that already exist. Test them. You may actually find a product that solves your problem perfectly. If so, congratulations, you just saved yourself months of work. Job done. Move to the next one.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The secret:&lt;/strong&gt; I was pretty amazed that just by switching up my habits and pushing myself out of my comfort zone, I fixed a bunch of problems. I started a 5-minute-a-day workout (which felt like a lot since I’m usually pretty inactive), and that kicked off a chain reaction, helping with stuff like back pain and improving my sleep.&lt;/p&gt;

&lt;p&gt;I also began volunteering at local non-profits, which really helped my networking. And the best part? It didn’t cost me a thing and didn’t involve any tech.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Three years later, most of the items are done, and I feel it’s time to go back to step one again very soon.&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.amazonaws.com%2Fuploads%2Farticles%2Ffzs2brbg9779fshj0dtf.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.amazonaws.com%2Fuploads%2Farticles%2Ffzs2brbg9779fshj0dtf.png" width="800" height="685"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  By simply adding a status to the list, I was able to track them easily.
&lt;/h6&gt;

&lt;h2&gt;
  
  
  3. Market research
&lt;/h2&gt;

&lt;p&gt;Alright, now the real game starts. If you didn’t find a solid fix for a big problem, your experience testing existing solutions earlier will help you see what’s missing. Here’s where most people go wrong, don’t start building just yet. Check out some marketing numbers first. Use &lt;a href="https://similarweb.cello.so/GyReSS5EKV2" rel="noopener noreferrer"&gt;SimilarWeb&lt;/a&gt; or &lt;a href="https://app.sensortower.com/overview/6602882160?country=US" rel="noopener noreferrer"&gt;SensorTower&lt;/a&gt; to gather some data about the players.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Check-in:&lt;/strong&gt; I prefer a market with big players, either in revenue or traffic, hitting millions a month. I’m a bit cautious about untapped markets. This probably isn’t the best problem to tackle while bootstrapping. I think I need to be really excited about the project to decide to keep going.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The secret:&lt;/strong&gt; By the way, being excited is a huge part of my process because building something is tough. There will be lots of times I’ll want to quit, so that excitement has to push me forward during those moments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  4. Now it’s your time to shine
&lt;/h2&gt;

&lt;p&gt;Now that you have a good idea of what you want and what the market looks like, split your time in two. If you are a product person, really force yourself to spend more time on marketing, and the opposite for marketing folks.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1. Test the market
&lt;/h3&gt;

&lt;p&gt;This next step totally changed the game for me: run ads and use simple forms to figure out acquisition costs. Getting users’ emails also helps you build a list of beta testers to stay in touch with. And yeah, you gotta talk to people dealing with the same problems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Marketing Requisites:&lt;/strong&gt; You have to spend money here, there’s no way around it. Someone who tells you otherwise is trying to trick you into buying their stuff. If you’re not willing to pay to find customers, either this problem isn’t that big a deal to you or you don’t really believe in your idea.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Last time I did this, I ran a Meta campaign using their Lead Online Forms. I tested my idea against 3 others to compare CAC and ended up finding another opportunity. Check out the &lt;a href="https://diego.horse/the-social-fall-the-bird-rise/" rel="noopener noreferrer"&gt;Bird Rise story&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4.2 Build an MVP
&lt;/h3&gt;

&lt;p&gt;While your ads are running, you can start building. This should answer technical questions and solve your specific problem. Keep it small and meaningful for now, because in less than six months, it will surely become a little monster with all the features added from user feedback.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tech Requisites:&lt;/strong&gt; Be careful with the scope and tech stack. You don’t want to build something that requires high server costs or maintenance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Use your own product. Remember, this came from your list of top problems you wanted to solve in your life. But try not to fall in love with your idea. Fall in love with the process of solving problems. Share your MVP with those first people from your initial Ads. Do the adjustments based on their feedback. You will have bugs. Many bugs. If users are not reporting bugs, you are not hearing them. It is hard to get good feedback. I still struggle here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Check-in:&lt;/strong&gt; While you’re going through this, you might realize your idea isn’t really fixing the problem. Technical issues pop up. CAC might be too high. The problem could be trickier than you expected. This is a good time to pause and think about whether you want to keep going. Quitting now isn’t a bad thing. It’s actually pretty smart. It saves you from wasting months on something that a solo person or small team can’t crack. Just go take a shower and have a good cry.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;I fixed all the bugs, adjusted the product based on early user feedback, and developed a decent version of the marketing strategy. Now it’s time for a reality check. What I want to figure out now is the real cost to attract paying customers and how much they’ll actually value my product. That way, I can get a clearer idea of whether this product will be sustainable or if I have enough money to keep it going.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Secret:&lt;/strong&gt; My go-to plans are short- and long-term subscriptions with a 3 to 7-day trial and lifetime discounts. This approach allows me to account for some costs related to the trial (CPT) preety fast and generate some revenue from lifetime discounts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I like weekly plans as an anchor for other plans and as a way to measure if the product is good enough. In a month or so, I should have a better idea of retention based on renewals.&lt;/p&gt;

&lt;p&gt;There will be many iterations here, from onboarding to pricing. Be patient before making major changes and try to get a good volume of users first.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How about growth hacks, virality, and organic strategies, Dieguito?&lt;br&gt;
– Your Favorite VC&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sorry, but I don’t trust organic growth as the main strategy (yet?). With the flood of AI-generated apps, welcome to the bloody ocean of the app market.&lt;/p&gt;

&lt;p&gt;Apple and Google wouldn’t surprise me if they start charging per app published instead of by developer account. The only people who don’t like paid acquisition strategies are VCs, they love to hear zero-marketing budget BS.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Measure
&lt;/h2&gt;

&lt;p&gt;The most important metrics for me are CAC related: CPT (Cost per trial), CPS (Cost per subscription) and ROAS. That is it. Retention, Profits and LTV are critical, but they take a while to measure meaningful data. You will change prices a lot until you find what works.&lt;/p&gt;

&lt;p&gt;Good tools to help you with that are &lt;a href="https://mixpanel.com/" rel="noopener noreferrer"&gt;Mixpanel&lt;/a&gt; (connected with the Meta API) and &lt;a href="https://revenuecat.com/" rel="noopener noreferrer"&gt;RevenueCat&lt;/a&gt;.&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.amazonaws.com%2Fuploads%2Farticles%2Ffnl0hy5b63f8f2qdynvh.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.amazonaws.com%2Fuploads%2Farticles%2Ffnl0hy5b63f8f2qdynvh.png" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Smart Keys Dashboard
&lt;/h6&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Check-in:&lt;/strong&gt; From those numbers, do another check-in. Scaling ads while bootstrapping is tricky and can get expensive quickly. Proceed with caution. You can see the blue line rising faster than revenue in the first chart. Six months later, I reevaluated to make the ad spend more sustainable.&lt;/p&gt;

&lt;p&gt;What about Experiments, weren’t you the king of A/B Tests?&lt;br&gt;
– Your Favorite Scientist&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First off, I’m not the king, maybe more like the Prince 💁‍♂️. I used to get super excited about experiments, especially the chance to discover something novel. I spent tons of hours designing, coding, and running experiments, sometimes with awesome results from tons of data points. But the weirdest part was that when we rolled out the experiment to all users, we didn’t see any change.&lt;/p&gt;

&lt;p&gt;What was probably happening was a lack of statistical power, which is a major issue in science itself. People often talk about statistical significance, but that’s really just an agreement that the result is unlikely to be due to chance, unlikely… unlikelly.&lt;/p&gt;

&lt;p&gt;Another thing to think about is what you actually measure. Experiments should ALWAYS be judged by the final metric, which is REVENUE. Tweaking middle metrics like signup rate or onboarding steps doesn’t always affect revenue. Sometimes a big jump in signup rate doesn’t do anything for revenue (I’ve even seen it go down 💸)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Secret:&lt;/strong&gt; So, when I start a new project, I usually don’t have the cash, team, or tons of data to run experiments. These days, I’m more into getting ideas from behavior construts that big companies have already tested a lot, like social proof, authority, commitment, scarcity, and so on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  10. Scale (or not)
&lt;/h2&gt;

&lt;p&gt;Welcome to the real world, you’re now a real player in the market. Scaling means you’ll be up against those big players you checked out months ago. Your campaign performance won’t be the same with your small budget. You’ll probably need more creatives, get more support tickets, and messing up your server or introducing a bug could disrupt thousands of users (While I’m writing this, I’m waiting for Apple to approve a bug fix for a version I messed up, and now users are stuck.).&lt;/p&gt;

&lt;p&gt;I consider it actually a good success if you can deliver a good product but can’t scale during the first months. You solved your own problem and helped other people solve theirs. Scaling takes time and requires good cash flow.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Secret:&lt;/strong&gt; If you’re going solo, find a buddy to do a bi-weekly check-in with. I’ve been doing this with a friend who’s also building stuff. Sharing progress and struggles helps keep you accountable and gives you new insights from another perspective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The truth:&lt;/strong&gt; This part of the process is still a work in progress, and I’m not totally sure I cracked the secret here. Either way, whether you managed to scale or not, it’s probably a good time to take a shower and have another cry.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  That’s it
&lt;/h2&gt;

&lt;p&gt;This is a live process. It involves some iterations and may take time. It has evolved since I read the nudge from the MAKE book that if your list of problems is small, you should make your life more interesting. I signed up for the &lt;a href="https://diego.horse/sf2-la-part-1/" rel="noopener noreferrer"&gt;540-mile bike ride from SF to LA&lt;/a&gt;, which brought me beautiful problems to solve.&lt;/p&gt;

&lt;p&gt;For &lt;a href="https://smartkeys.so/" rel="noopener noreferrer"&gt;Smart Keys&lt;/a&gt;, I followed most of the steps above. However, I admit that in other projects, I skip some parts I don’t like much, such as properly testing the market.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://diego.horse/tag/air-fiesta/" rel="noopener noreferrer"&gt;Air Fiesta&lt;/a&gt; is a very poor example of a project that failed on many levels. It started by not addressing any of my problems, was technically complex, had a huge scope, and I did inadequate market research. I did it simply because I had free time and was excited about building a game using the Google Maps SDK related to a cause. I even added to my list of problems just to justify its development: “I want to create games again.” 🥸&lt;/p&gt;

&lt;p&gt;But I am trying to be better at it. &lt;a href="http://birdrise-therising.html/" rel="noopener noreferrer"&gt;Bird Rise&lt;/a&gt; was actually a pivot inspired by insights during the market test. And Air Fiesta and other &lt;a href="https://diego.horse/tiny-games-big-feelings/" rel="noopener noreferrer"&gt;tiny games&lt;/a&gt; actually brought a main insight about using games as a marketing tool. So maybe I am learning something after all.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>indiehackers</category>
      <category>startup</category>
      <category>career</category>
    </item>
    <item>
      <title>Tiny Games, Big Feelings</title>
      <dc:creator>Diego Dotta</dc:creator>
      <pubDate>Sat, 22 Nov 2025 00:36:56 +0000</pubDate>
      <link>https://dev.to/diegodotta/tiny-games-big-feelings-4oke</link>
      <guid>https://dev.to/diegodotta/tiny-games-big-feelings-4oke</guid>
      <description>&lt;p&gt;Everything actually started when I played &lt;a href="https://jordanmagnuson.itch.io/loneliness" rel="noopener noreferrer"&gt;Loneliness&lt;/a&gt;. What a strange, quiet punch of a game. I wasn’t expecting much (it’s just little squares on a white screen) but somehow it managed to pull more emotions out of me in two minutes than most AAA games do in fifty hours. I walked away confused and weirdly emotional, like someone had whispered something important into my ear and then vanished.&lt;/p&gt;

&lt;p&gt;So of course I did the only reasonable thing: I became obsessed. I hunted down the creator, &lt;a href="https://www.jordanmagnuson.com/" rel="noopener noreferrer"&gt;Jordan Magnuson&lt;/a&gt;, and ended up reading his book &lt;a href="https://www.gamepoemsbook.com/" rel="noopener noreferrer"&gt;Game Poems&lt;/a&gt;, which didn’t help at all because now I’m even more obsessed.&lt;/p&gt;

&lt;p&gt;The whole idea that games can be short, intentional emotional gestures suddenly made sense. Then I stumbled upon &lt;a href="https://demian.ferrei.ro/snake" rel="noopener noreferrer"&gt;URL Snake&lt;/a&gt;, this tiny absurd miracle living inside the URL bar, built entirely with Braille characters. I did what I always do when I find something tiny and clever: I became obsessed with its creator, &lt;a href="https://demian.ferrei.ro/" rel="noopener noreferrer"&gt;Demian Ferreiro&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So on a sunny weekend, I decided to experiment with those ideas. The first result was &lt;a href="https://diego.horse/jump/" rel="noopener noreferrer"&gt;Tiny Horse&lt;/a&gt;, a tiny creature leaping across my URL bar like it’s trying to outrun my unfinished tasks.&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.amazonaws.com%2Fuploads%2Farticles%2F1zkwxefdvbpu4580dkl5.gif" 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.amazonaws.com%2Fuploads%2Farticles%2F1zkwxefdvbpu4580dkl5.gif" alt="Tiny Horse" width="1124" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then came &lt;a href="https://diego.horse/tiny-mario/" rel="noopener noreferrer"&gt;Tiny Mario&lt;/a&gt;, who took the same microscopic canvas and somehow turned it into a full side-scrolling adventure powered entirely by Braille characters and misplaced confidence.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=6i1PxtaBfZ0" rel="noopener noreferrer"&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.amazonaws.com%2Fuploads%2Farticles%2Favbww6e7rbp3hbhof4un.jpg" alt="Tiny Mario" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I actually built this second one in secret from Leandra because I was supposed to be working on a different project and not making games anymore. I kept two instances of &lt;a href="https://windsurf.com/refer?referral_code=oy0hdqpvkz4b88ng" rel="noopener noreferrer"&gt;Windsurf&lt;/a&gt; open, and whenever she walked by, I switched to the main project (she is the boss).&lt;/p&gt;

&lt;p&gt;I was surprised that I could work on two projects at the same time, with one assistant coding some complex tasks while working with the other. Obviously, I was paying much more attention to the game though. ;p&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.amazonaws.com%2Fuploads%2Farticles%2Ffcsl0922t3dbs7t2dm3q.gif" 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.amazonaws.com%2Fuploads%2Farticles%2Ffcsl0922t3dbs7t2dm3q.gif" alt="Alt-tab meme" width="398" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They’re not big games. They’re not meant to be. They’re little moments. Digital haikus. Emotional blips. I build them fast, break them faster, and still feel strangely proud of them.&lt;/p&gt;

&lt;p&gt;And you know what? While building and playing them, I kept noticing how these tiny games trigger emotions so quickly. Simple graphics, a couple of sound cues, and suddenly I’m laughing out loud on a Saturday night at 11 p.m. because I made Tiny Mario slip into an underground level through tiny pipes.&lt;/p&gt;

&lt;p&gt;Besides being simple, they include classic casual game elements that spark some adrenaline: scores, countdown, enemies, rewards, obstacles, and elements of surprise. Something I haven’t been able to add to &lt;a href="https://dev.to/tag/air-fiesta"&gt;Air Fiesta&lt;/a&gt; yet.&lt;/p&gt;

&lt;p&gt;If you want to see what all this tiny-game energy looks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tiny Horse&lt;/strong&gt; → &lt;a href="https://diego.horse/jump" rel="noopener noreferrer"&gt;https://diego.horse/jump&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tiny Mario&lt;/strong&gt; → &lt;a href="https://diego.horse/tiny-mario" rel="noopener noreferrer"&gt;https://diego.horse/tiny-mario&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Both projects are open source on my &lt;a href="https://github.com/diegodotta" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if you want to feel the thing that started all this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Loneliness&lt;/strong&gt; → &lt;a href="https://jordanmagnuson.itch.io/loneliness" rel="noopener noreferrer"&gt;https://jordanmagnuson.itch.io/loneliness&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL Snake&lt;/strong&gt; → &lt;a href="https://demian.ferrei.ro/snake" rel="noopener noreferrer"&gt;https://demian.ferrei.ro/snake&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Game poems are small, but they hit hard, like tiny sparks pretending they aren’t capable of starting whole wildfires. And honestly, maybe that’s exactly what makes them beautiful… and powerful.&lt;/p&gt;




&lt;h2&gt;
  
  
  Nov 18th Update
&lt;/h2&gt;

&lt;p&gt;I wasn’t expecting people to get this excited about a tiny game. I posted it on &lt;a href="https://www.producthunt.com/products/tiny-mario?launch=tiny-mario" rel="noopener noreferrer"&gt;Product Hunt&lt;/a&gt; and &lt;a href="https://www.reddit.com/r/InternetIsBeautiful/comments/1ovo0xu/play_tiny_mario_on_your_url_bar/" rel="noopener noreferrer"&gt;Reddit&lt;/a&gt; just for fun and suddenly folks were actually into it. It’s not the kind of thing people usually share there, but I guess we’re all craving fewer AI products and more silly things like this.&lt;/p&gt;

&lt;p&gt;Give it a vote if you feel like it. We already beat a Google product (which feels surreal and funny at the same time).&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.amazonaws.com%2Fuploads%2Farticles%2Fnmh1vnlglc6r1sg56i04.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.amazonaws.com%2Fuploads%2Farticles%2Fnmh1vnlglc6r1sg56i04.png" alt="Tiny Mario #9 Place" width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>gamedev</category>
      <category>javascript</category>
      <category>braille</category>
    </item>
    <item>
      <title>Air Fiesta: When the Balloons Multiplied</title>
      <dc:creator>Diego Dotta</dc:creator>
      <pubDate>Tue, 28 Oct 2025 02:05:15 +0000</pubDate>
      <link>https://dev.to/diegodotta/air-fiesta-when-the-balloons-multiplied-57l3</link>
      <guid>https://dev.to/diegodotta/air-fiesta-when-the-balloons-multiplied-57l3</guid>
      <description>&lt;p&gt;There was a time when everyone shared a single balloon. That was Airtales, one collective flight drifting wherever the crowd decided. Democracy by wind. Chaos by design. It was beautiful, but also… a little limiting. People wanted to explore their own skies. This is &lt;a href="https://diego.horse/airtales-story/" rel="noopener noreferrer"&gt;why it started&lt;/a&gt; and &lt;a href="https://diego.horse/airtales-when-the-balloon-landed/" rel="noopener noreferrer"&gt;how it ended&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That’s how &lt;a href="https://airfiesta.fm/" rel="noopener noreferrer"&gt;Air Fiesta&lt;/a&gt; happened, a pivot, or maybe a parallel universe. Now every player has their own balloon. You can float above your neighborhood, drift over famous cities, or join in festivals with friends. No borders, no passport required.&lt;/p&gt;

&lt;p&gt;Underneath it all, it still runs on the same energy: curiosity, community, and a touch of absurd optimism that maybe the world makes more sense from 300 feet up.&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.amazonaws.com%2Fuploads%2Farticles%2Fyqzi5n2bk9ah0kny1fdt.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.amazonaws.com%2Fuploads%2Farticles%2Fyqzi5n2bk9ah0kny1fdt.png" alt="Nature and weather conditions are your challenges."&gt;&lt;/a&gt;&lt;em&gt;Nature and weather conditions are your challenges.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What’s New
&lt;/h2&gt;

&lt;p&gt;Air Fiesta is built on &lt;a href="https://mapsplatform.google.com" rel="noopener noreferrer"&gt;Google Maps SDK&lt;/a&gt;, so what you see is the real planet. You can tune into local radio stations while you fly (because every city sounds different).&lt;/p&gt;

&lt;p&gt;You can take photos of your journey, discover hidden treasures, and battle weather that’s way less forgiving than it looks. Gusty winds, thermals, fog, even flocks of birds (the kind of chaos that makes you laugh right before it throws you off course).&lt;/p&gt;

&lt;p&gt;And what about the balloon festivals? They’re still happening. They will probably change into something simpler. Right now, it’s a scavenger hunt with virtual friends. But it seems a bit complicated, so it will likely become more like freely collecting hidden gems.&lt;/p&gt;

&lt;p&gt;One big improvement was the mobile experience. The game is still based on web technology (ThreeJS), which is tricky to run on mobile, but you can try it out on the &lt;a href="https://apps.apple.com/us/app/air-fiesta-on-google-earth/id6751870549" rel="noopener noreferrer"&gt;App Store&lt;/a&gt; or &lt;a href="https://play.google.com/store/apps/details?id=fm.airfiesta.app" rel="noopener noreferrer"&gt;Play Store&lt;/a&gt;. Coming soon on Steam.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/SYa2TpslXAg"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;




&lt;h3&gt;
  
  
  Why I Still Care About Radio
&lt;/h3&gt;

&lt;p&gt;Radio’s the heartbeat of Air Fiesta. I’ve always loved it, the crackle, the local ads, the DJs who sound like they’ve seen things. There’s something deeply human about tuning into a city’s voice while you’re hovering over it.&lt;/p&gt;

&lt;p&gt;I’m reaching out to stations now, (community, college, indie, public) to ask permission to float them inside the game. Because I want players to hear the places they fly over, not just see them.&lt;/p&gt;

&lt;p&gt;If you run a station, you can see a preview of what that looks like:&lt;br&gt;
See a balloon radio in &lt;a href="https://airfiesta.fm/watch/evr" rel="noopener noreferrer"&gt;New York&lt;/a&gt; and another in the &lt;a href="https://airfiesta.fm/watch/kqed" rel="noopener noreferrer"&gt;Bay Area&lt;/a&gt;. This is more like a non-interactive mode where you can “watch” other players.&lt;/p&gt;

&lt;p&gt;Special thanks to &lt;a href="https://www.radio-browser.info/" rel="noopener noreferrer"&gt;Radio Browser&lt;/a&gt; technology for providing the geo-position of radios worldwide for free.&lt;/p&gt;


&lt;h3&gt;
  
  
  Where Air Fiesta Is Cancelled
&lt;/h3&gt;

&lt;p&gt;Not everywhere is safe to fly.&lt;/p&gt;

&lt;p&gt;Inspired by the &lt;a href="https://www.cfr.org/global-conflict-tracker" rel="noopener noreferrer"&gt;Global Conflict Tracker&lt;/a&gt; and &lt;a href="https://freedomflotilla.org/" rel="noopener noreferrer"&gt;Freedom Flotilla&lt;/a&gt;, I mapped ongoing conflicts around the world: wars, occupations, humanitarian crises. The result was staggering. In those regions, Air Fiesta goes silent.&lt;/p&gt;

&lt;p&gt;It’s not meant as protest or pity, more like a pause. When the world is burning, sometimes silence says more than scenery.&lt;/p&gt;

&lt;p&gt;Maybe one day those places will light up again with music, laughter, and balloons rising together. Until then, the silence stays.&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.amazonaws.com%2Fuploads%2Farticles%2Fj5h4hxipromur8iufog6.jpg" 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.amazonaws.com%2Fuploads%2Farticles%2Fj5h4hxipromur8iufog6.jpg" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  Feed and Gallery
&lt;/h3&gt;

&lt;p&gt;Since Airtales has a feature that is quite unique (the camera), like a real balloon adventure, you can take pictures of your views. It’s no different here; people feel excited about doing that, so I keep it.&lt;/p&gt;

&lt;p&gt;The improvement from the previous version is that you can now see pictures, messages, and other balloon interactions in a feed format.&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.amazonaws.com%2Fuploads%2Farticles%2Fwcamk40xa53n62jh7ikz.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.amazonaws.com%2Fuploads%2Farticles%2Fwcamk40xa53n62jh7ikz.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  What’s missing?
&lt;/h3&gt;

&lt;p&gt;I think there are important pieces missing or not quite right. The story, for example, seems weak or almost nonexistent. Another important aspect is world-building. Currently, interactions with the world are almost zero. I think players should be able to build or change something in the real world. Right now, it’s almost like a ‘leave no trace’ approach, but it could be cool if they could move things around, clean the ocean, deliver letters, or even destroy borders :p&lt;/p&gt;

&lt;p&gt;You can see follow the progress on &lt;a href="https://diegodotta.itch.io/airfiesta/devlog" rel="noopener noreferrer"&gt;Itch.io&lt;/a&gt;, for the first time I’m documenting the changelog there, it’s quite interesting.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/BQl88QLsY1s"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;




&lt;h3&gt;
  
  
  The Sky Is the Limit
&lt;/h3&gt;

&lt;p&gt;Air Fiesta isn’t about competition. There’s no score. No finish line. Just weather, music, and motion. It’s a little weird and a little hopeful, a floating experiment in what happens when you mix geography, sound, and strangers who want to explore together. This won’t trigger dopamine traps, and you won’t become addicted to it.&lt;/p&gt;

&lt;p&gt;Maybe that’s the game I’ve always wanted to play: one where the world is the level, and connection is the win condition.&lt;/p&gt;

&lt;p&gt;✈️ Play at &lt;a href="https://airfiesta.fm" rel="noopener noreferrer"&gt;airfiesta.fm&lt;/a&gt; or read the &lt;a href="https://airfiesta.fm/manifesto/index.html" rel="noopener noreferrer"&gt;manifesto&lt;/a&gt; if you’re into that kind of thing.&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>showdev</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>Neuralese: The Most Spoken Language You’ll Never Speak</title>
      <dc:creator>Diego Dotta</dc:creator>
      <pubDate>Tue, 06 May 2025 02:37:50 +0000</pubDate>
      <link>https://dev.to/diegodotta/neuralese-the-most-spoken-language-youll-never-speak-51hl</link>
      <guid>https://dev.to/diegodotta/neuralese-the-most-spoken-language-youll-never-speak-51hl</guid>
      <description>&lt;p&gt;Somewhere between thinking and speaking, there’s a strange place where meaning starts to solidify. It’s not quite a word yet. More like a haze of associations. A mental sketch your brain tries to translate into something shareable. Sometimes it works. Most of the time it doesn’t, at least for me. I tend to mumble a lot.&lt;/p&gt;

&lt;p&gt;That private language in your head, the one you use to talk to yourself, isn’t English or Portuguese or Python. &lt;a href="https://www.scientificamerican.com/article/you-dont-need-words-to-think/" rel="noopener noreferrer"&gt;It’s not even a language, really.&lt;/a&gt; It’s raw and messy. A kind of silent shorthand sculpted by experience. Try catching it. Try explaining it. It slips through like fog in your fingers.&lt;/p&gt;

&lt;p&gt;This isn’t a linguistics paper. It’s a thought experiment about the strange, alien dialects spoken by machines, and what they might reveal about how we understand language, and ourselves. This is speculative. It’s not meant as a technical model of how LLMs work or how humans process language, just a meditation on how meaning can take forms we may never be able to speak.&lt;/p&gt;

&lt;h2&gt;
  
  
  The language of thought (According to machines)
&lt;/h2&gt;

&lt;p&gt;Science is already poking around in there. Researchers are feeding brain signals into neural networks and getting fuzzy images back. They’re trying to reverse-engineer what we see, dream or remember. &lt;a href="https://www.nature.com/articles/s41598-023-42891-8" rel="noopener noreferrer"&gt;Some of the reconstructions look like fever dreams&lt;/a&gt;. Others are eerily close. It’s like watching the mind on a bad TV signal, but the tech keeps getting better.&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.amazonaws.com%2Fuploads%2Farticles%2Fdjoztqllv3mj9ndrx1zw.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.amazonaws.com%2Fuploads%2Farticles%2Fdjoztqllv3mj9ndrx1zw.png" alt="AI re-creations of images based on brain scans (bottom row) match the layout, perspective, and contents of the actual photos seen by study participants (top row)" width="800" height="388"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;AI re-creations of images based on brain scans (bottom row) match the layout, perspective, and contents of the actual photos seen by study participants (top row)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then there’s the way we connect our minds to each other. Through letters carved into stone. Through cave paintings, vinyl records, emojis, GIFs, memes. Through every kludge we’ve invented to make what’s in here vaguely resemble what’s in there. Language is our duct tape for consciousness.&lt;/p&gt;
&lt;h2&gt;
  
  
  What the machines whisper when we’re not listening
&lt;/h2&gt;

&lt;p&gt;When we started teaching machines, we handed them the same duct tape. Natural language. Our language. We told them, here, talk like us. So they did. Or at least, they pretended to and we believed.&lt;br&gt;
Quick cheat sheet before we tangle the wires. There are three very different “languages” in this story (I can hear the linguists sharpening their red pencils):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Human languages: messy, culture‑soaked, built for wet brains and bad at precision.&lt;/li&gt;
&lt;li&gt;Machine protocols (non-neural): JSON blobs, HTTP headers, rule-bound micro-dialects that leave no room for doubt.&lt;/li&gt;
&lt;li&gt;Latent representations (neural): the private vector soup inside one model, never transmitted (outside a lab demo), never meant for ears.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ChatGPT. Alexa. Siri. Every chatbot trying to pass for clever at dinner sits in bucket one when it chats with us. But here’s the twist. When machines talk to each other, they skip the human stuff. No syntax, no grammar, no metaphors.&lt;/p&gt;

&lt;p&gt;When Alexa calls Roomba they are not exchanging cute phrases. Alexa fires a strict micro‑dialect packet (JSON over HTTPS). That’s bucket two, a protocol, not a mind‑to‑mind vector swap. Efficient, silent, built for zero confusion.&lt;/p&gt;

&lt;p&gt;Those packet‑speaking systems are narrow tools, nothing close to AGI. But we are already wiring up broader agents that learn on the fly, pick their own tactics, and only visit a language model when they need to chat with us. For talking to each other they could ditch words entirely and trade vectors, numbers, tokens, dense nuggets of meaning we can’t read or pronounce.&lt;/p&gt;

&lt;p&gt;Is that Neuralese? Maybe. It is not a code we will ever study in a classroom, not because it is too complex, but because it was never meant for us. If a signal can move intent across silicon and spin motors into action without leaving a human‑readable trace, “language” feels like the best word we have.&lt;/p&gt;

&lt;p&gt;Do LLMs actually communicate inside the stack? Not like two agents tossing discrete symbols in a reinforcement game. A single model is one giant function. Its only chatter is with itself. Neuralese might be closer to private thoughts than walkie‑talkie slang. If you have a paper that shows real agent‑to‑agent symbol swaps, drop a link. I want to dig in.&lt;/p&gt;
&lt;h2&gt;
  
  
  Inside the black box: The unspoken language of AI
&lt;/h2&gt;

&lt;p&gt;They don’t think. Not really. They don’t speak, understand, or mean. What they do is behave in ways that simulate meaning so convincingly, we reflexively fill in the gaps. We anthropomorphize (everything, as always). And in that space between their mimicry and our projection, something emerges, something like communication. Or, as Rodney Brooks said, “…we over-anthropomorphize humans, who are, after all, mere machines.”&lt;/p&gt;

&lt;p&gt;Back to the (non?)language Neuralese, this dense tangle of vector math, no rules or roots that only appears as thought when reflected in our direction.&lt;/p&gt;

&lt;p&gt;It's not that the model knows what a cat is. It’s that when we ask it about cats, it activates just enough of the “catness” region in its mathematical dreamspace to give us an answer that feels right. That feeling is the trick. The illusion. But also the revelation. &lt;/p&gt;

&lt;p&gt;But this new language lives inside the black box. It’s the internal chatter of large language models. The soup of token embeddings sloshing around under the hood. It's not designed to be elegant or expressive. It's designed to get the job done.&lt;/p&gt;

&lt;p&gt;Human language is a marvel, full of ambiguity, poetry, subtext, and shared cultural connections. But to a machine, it’s just noise, indirect and redundant, made for soft, wet brains. Machines might not even need a large language model to communicate with each other.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“But Diego, LLMs are still hallucinating and getting things wrong” – The LLM Hater&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sure. A lot of them are. And I might be completely off here. But models built to reason are already proving more accurate. Chain-of-thought, tree-of-thought and other techniques all try to force a step-by-step breakdown. It’s like watching a toddler narrate their Lego build. Clunky, but it works. And here’s where things get weird. That inner language, the model’s inner monologue, starts to feel just as chaotic and hazy as ours. Thinking burns energy. Nature figured out a way to make that work for us. We made machines. They’re still figuring it out.&lt;/p&gt;

&lt;p&gt;Why should a model have to spell out a whole grammatically correct essay to think something through? Why not let it mumble to itself in its own weird way?&lt;/p&gt;

&lt;p&gt;I ran a dumb little experiment. Just wanted to see if tweaking the way a model reasons, shifting its “language” a bit, could save on tokens without wrecking the answer.&lt;/p&gt;
&lt;h2&gt;
  
  
  A little dumb experiment
&lt;/h2&gt;

&lt;p&gt;By using only prompt engineering, I wanted to see if I could get the model to reason in a language I don’t understand, but still produce the correct final answer, all while keeping it fast and using fewer tokens. I tested only the latest mini OpenAI models that don’t have reasoning embedded. I chose a classic test case that models without reasoning usually fail.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Question: “Sally has 3 brothers, each with 2 sisters. How many sisters does Sally have?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Test 1: Just asked the question straight up.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Final answer: Sally has 2 sisters&lt;br&gt;
*871ms, 8 tokens, and wrong answer ❌&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Test 2: Wrapped the whole thing in a JSON schema. Forced the model to explain each step. It cost 20 times more to get it right.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Final answer: Sally has 1 sister&lt;br&gt;
*2.559ms, 164 tokens, right answer ✅&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Test 3: Limited the vocabulary to words with four letters or less. Still got the right answer. Faster and over 60% more cost-effective than test 2.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Final answer: Sally has 1 sister&lt;br&gt;
*1.633ms, 64 tokens, right answer✅&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The final test was successful on the 4o-mini, 4.1-mini, and 4.1-nano. Even the nano, which I find almost useless, got things right.&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.amazonaws.com%2Fuploads%2Farticles%2Fc3x1jq90wn7cwktkgu4y.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.amazonaws.com%2Fuploads%2Farticles%2Fc3x1jq90wn7cwktkgu4y.png" alt="Optimized reasoning: “Sally has 3 bros, Each bro has 2 sis. Sally is one sis. So, the other sis count is 1.”" width="800" height="368"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Optimized reasoning: “Sally has 3 bros, Each bro has 2 sis. Sally is one sis. So, the other sis count is 1.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The best result I got was this reasoning that sounded like stripped-down English. Kind of minimalist. With “bros” and “sis”. No fluff. And that seemed to help. There’s no judgment on grammar when it comes to reasoning. Clarity doesn’t always need correctness.&lt;/p&gt;

&lt;p&gt;To be honest, this wasn’t test 3. It was more like test 100. I tried switching to other languages. Simplified Chinese worked better than expected, each symbol packs more meaning. Telegraph-style English helped too. Fewer filler words, less ambiguity. Even Simplified English made a difference. Some other experiments failed, costing more or failing to find the answer, such as using logic symbols, not using vowels or spaces during reasoning, which made sense based on &lt;a href="https://seantrott.substack.com/p/tokenization-in-large-language-models" rel="noopener noreferrer"&gt;how token prediction works&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This was not a breakthrough strategy for cutting reasoning costs or use that as &lt;a href="https://en.wikipedia.org/wiki/Machine_to_machine" rel="noopener noreferrer"&gt;machine-to-machine (M2M) communication&lt;/a&gt;. But it’s a nudge. A clue. A hint that maybe we can think better by saying less. And it’s still a long way from pure vectors or emergent protocols. But we might unlock cheaper, faster, more energy-efficient reasoning (unless someone builds a clean and infinite energy source first).&lt;/p&gt;
&lt;h2&gt;
  
  
  A little sci-fi thought experiment
&lt;/h2&gt;

&lt;p&gt;So, if you're a linguist or an MS and you haven't gotten upset about what you've read so far, now's the time.&lt;/p&gt;

&lt;p&gt;Let’s imagine that if there is a language machines use to communicate with each other, why not a programming language created by them that is efficient and probably impossible for us to understand?&lt;/p&gt;

&lt;p&gt;Let’s call it Noēsis+ (from the Greek for “pure thought”). It is a token-only language. Each token is meaningless on its own. Meaning emerges only in the context of thousands of other tokens, across time, weighted by past executions.&lt;/p&gt;

&lt;p&gt;Imagine each token as a coordinate, one point in a vast, high-dimensional landscape. Not with meaning on its own, but with potential. What matters isn’t what the token “says,” but where it leads.&lt;/p&gt;

&lt;p&gt;Tokens:&lt;br&gt;
Arbitrary identifiers, like:&lt;br&gt;
&lt;code&gt;ɸqz, ∆9r, aal, ⊠7, gr_, etc.&lt;/code&gt;&lt;br&gt;
No keywords. No syntax. No punctuation. No variables.&lt;/p&gt;

&lt;p&gt;Sequence-as-Code:&lt;br&gt;
In Noēsis, tokens don’t have fixed meanings. Execution isn’t logic, it’s flow. Meaning emerges from proximity, repetition, and order, the way patterns in machine learning models seem to take shape across vast sequences. Not like programming. More like resonance. A mood that builds as tokens pass in relation to one another.&lt;/p&gt;

&lt;p&gt;Compiled into Behavior:&lt;br&gt;
Imagine a language where each token isn’t a command, but a vector. Not syntax, but coordinates in a sprawling, invisible space.&lt;/p&gt;

&lt;p&gt;Programs in Noēsis don’t “run” like code. They move. They drift across latent vector fields, tracing paths shaped by token proximity, past history, and ambient state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ɸqz ∆9r ∆9r aal ⊠7 ⊠7 ⊠7 gr_ ∞yx ɸqz gr_ gr_ ⊠7 xaz ɸqz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same program, different result, depending not on what was written, but on when and where it was run. Like a thought that feels different depending on your mood. It’s almost as if it’s meant to make us anxious, and maybe machines could get anxious too?&lt;/p&gt;

&lt;p&gt;Not that machines “feel.” But if their outputs jitter with context, if the same input drifts into new behaviors, does it matter? From the outside, it looks like mood. Like uncertainty. Like… unease&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Congrats, you burned 1,800 tokens to say nada, tech bro.”&lt;br&gt;
– A linguist ex-friend&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Point taken. You found my weak spot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Syntax of a mind that isn’t ours
&lt;/h2&gt;

&lt;p&gt;Jokes a part, while we keep polishing the human-sounding outputs, the real magic might be in listening closer to the alien syntax already unfolding under the surface. Well, alien because this language will evolve by a technology that wasn’t created by us, but by our creations.&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.amazonaws.com%2Fuploads%2Farticles%2F8to6nxt1irrf0jw8rtm7.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.amazonaws.com%2Fuploads%2Farticles%2F8to6nxt1irrf0jw8rtm7.png" alt="A word after a word after a word is power - Margaret Atwood" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So yeah. Neuralese. You’ll never speak it. You’ll never read it. But it might end up being the most fluent language on the planet.&lt;/p&gt;

&lt;p&gt;And we’re the ones with the accents.&lt;/p&gt;




&lt;h2&gt;
  
  
  Changelog &amp;amp; Mea Culpas
&lt;/h2&gt;

&lt;p&gt;The first version of this article triggered strong emotions on Reddit. I updated it and I ended up getting some great insights though, thanks to all the anonymous experts who educationally slapped me into a less “unscientific” and “idiotic” thought experiment.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>ai</category>
      <category>discuss</category>
      <category>neuralese</category>
    </item>
    <item>
      <title>The Vibe Life: Building Smart Keys for Mac</title>
      <dc:creator>Diego Dotta</dc:creator>
      <pubDate>Fri, 25 Apr 2025 00:17:46 +0000</pubDate>
      <link>https://dev.to/diegodotta/the-vibe-life-building-smart-keys-for-mac-pfn</link>
      <guid>https://dev.to/diegodotta/the-vibe-life-building-smart-keys-for-mac-pfn</guid>
      <description>&lt;p&gt;I didn’t realize I was about to enter the “vibe” industry when I started building Smart Keys. All I really wanted was a way to sound fluent in languages without doing the hard work. Let’s be real: learning languages is tough. So, I built an app that lets me fake my english fluency until I make it. Besides hating this reference, the thing here is that I’ll probably never make it. I may not be as fluent as I sound using tools like this.&lt;/p&gt;

&lt;p&gt;Still, Smart Keys did the job for me on my phone. It solved my laziness problem and gave me a sense of accomplishment. Translate a message, change to a more casual tone, proofread an email, all with one tap. Suddenly, I was hooked. This tiny app had me feeling like a fluent native speaker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bringing the Vibe to My Desktop
&lt;/h2&gt;

&lt;p&gt;Once Smart Keys worked its magic on my phone, I thought: why not bring this vibe to my desktop? I wanted to cut down on the constant back-and-forth between tabs, the endless browser windows, and that infuriating cycle of copy-pasting. Small tasks, like checking email, sending a reply, or fixing a bug, don’t require much brainpower, but they drain your energy nonetheless.&lt;/p&gt;

&lt;p&gt;So, I created Smart Keys for Mac.&lt;/p&gt;

&lt;p&gt;The goal was simple: stay in my flow, move through tasks without jumping between apps, and avoid losing focus on anything. I wanted to type, hit a shortcut, and keep moving. Proofread, translate, fix code, all without leaving the current task.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The Perils of a One-Code Solution
&lt;/h2&gt;

&lt;p&gt;Now, if you’ve ever tried to port an app from iOS to macOS, you’ll know it’s not as simple as change deployment target and calling it a day. That’s what I thought, but nope. The idea of maintaining one codebase sounded genius: keep it efficient, keep it synced, keep the maintenance low. But here’s the thing: macOS and iOS are like distant cousins. They share some traits but are entirely different creatures.&lt;/p&gt;

&lt;p&gt;“If debugging is the process of removing software bugs, then programming must be the process of putting them in.”&lt;br&gt;
– Edsger Dijkstra&lt;/p&gt;

&lt;p&gt;“Two platforms, one codebase” sounds like a dream, but I quickly realized that you can’t just slap a mobile UI onto a desktop app and call it a day. The screen sizes, input methods, window management, all these small details had to be adjusted. It’s like trying to fit a square peg into a round hole, but making it work without losing the essence of what you built.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fine Line Between Efficiency and Overload
&lt;/h2&gt;

&lt;p&gt;Incorporating macOS-specific optimizations wasn’t as simple as resizing windows. The app had to manage multiple displays, adjust for different screen sizes, and still feel fluid while taking advantage of the desktop’s power. Every change, every tweak, led to a cascade of other adjustments. Maintaining a single codebase was efficient in theory, but it created a lot of headaches along the way.&lt;/p&gt;

&lt;p&gt;I spent more time testing than I care to admit, making sure one small change didn’t break something somewhere else. But that’s the process. There’s no such thing as an easy app transition (yet).&lt;/p&gt;

&lt;h2&gt;
  
  
  Selling a Quiet Product That Does a Lot
&lt;/h2&gt;

&lt;p&gt;Now that Smart Keys mostly works, the challenge has shifted. I’m not wrestling with bugs as much as I’m wrestling with words. Building a product that blends into your day is one thing. Explaining it without making it sound like a blender full of features is another.&lt;/p&gt;

&lt;p&gt;It rewrites. It translates. It fixes weird grammar and polishes sloppy code. All in the background, with shortcuts you barely notice. That’s the magic. And also the problem.&lt;/p&gt;

&lt;p&gt;It’s hard to pitch a tool that isn’t trying to impress you. It just wants to help and then get out of the way. Try to summarize it in one sentence and you either oversimplify or overcomplicate. Try to be specific and it starts to sound like five tools in a trench coat.&lt;/p&gt;

&lt;p&gt;“First, write the press release. Then, build the product.”&lt;br&gt;
– Not me&lt;/p&gt;

&lt;p&gt;So now I’m figuring out how to talk about it without killing the simplicity. Selling a quiet product in a world that rewards loud ones. Making clarity feel exciting without dressing it up too much.&lt;/p&gt;

&lt;p&gt;Still, every time I’m stuck rewriting copy for the tenth time, it’s right there. I hit a shortcut, smooth things out, and move on.&lt;/p&gt;

&lt;p&gt;Sure, half the time I’m fixing the thing I just built, but hey, at least I’ve got good shortcuts for the apology emails.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>ai</category>
      <category>grammar</category>
      <category>smartkeys</category>
    </item>
    <item>
      <title>Store Conversion? More like Store Distraction.</title>
      <dc:creator>Diego Dotta</dc:creator>
      <pubDate>Tue, 04 Feb 2025 00:15:02 +0000</pubDate>
      <link>https://dev.to/diegodotta/store-conversion-more-like-store-distraction-444k</link>
      <guid>https://dev.to/diegodotta/store-conversion-more-like-store-distraction-444k</guid>
      <description>&lt;p&gt;Apple’s shiny Benchmark Metrics are BS, but don’t be fooled. &lt;/p&gt;

&lt;p&gt;I learned that the hard way while feeling proud of myself as I rearranged screenshots, polished keywords, and declared I’d cracked the code. Smart Keys conversion rate soared, my proceeds per user looked stellar, and I’d pat myself on the back every time I glanced at the numbers.&lt;/p&gt;

&lt;p&gt;Then it hit me that I was clinging to illusions, metrics that look good on paper but hide the gritty reality of crashes, retention, and actual profitability.&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.amazonaws.com%2Fuploads%2Farticles%2F3ys9146qkh0fnbu0x1fy.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.amazonaws.com%2Fuploads%2Farticles%2F3ys9146qkh0fnbu0x1fy.png" alt="App Store Benchmark Report" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s the short version of what I learned:&lt;/p&gt;

&lt;p&gt;💩 1. Store Conversion: Ads and external promotions can juice your stats, making conversion look like a high score when it’s basically pay-to-win.&lt;/p&gt;

&lt;p&gt;💸 2. Proceeds per Paying User: This can appear golden, until you remember acquisition costs can burn a hole in your wallet.&lt;/p&gt;

&lt;p&gt;👑 3. Crashes: This is real gold. On a small team, testing across all devices and iOS versions is no walk in the park, this metric shows you if your app is on fire before the reviews come in hot.&lt;/p&gt;

&lt;p&gt;🐎 4. Retention (D1, D7, D28): A slow-burn test of whether users actually come back. Trial periods and paywalls can skew it, so patience is key.&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.amazonaws.com%2Fuploads%2Farticles%2Ffgxnnkk7enyr7npliji8.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.amazonaws.com%2Fuploads%2Farticles%2Ffgxnnkk7enyr7npliji8.png" alt="Retention Reports" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The truth is, Apple’s polished dashboards won’t give you the full picture. I’ve learned more from &lt;a href="https://every.to" rel="noopener noreferrer"&gt;Every&lt;/a&gt; Inc. and the community #BuildingInPublic than from any set of curated stats or ASO gurus.&lt;/p&gt;

&lt;p&gt;Want to dive deeper into the real numbers and see how I’m trying to keep things honest? Check out the full metrics and analysis on my blog at &lt;a href="https://diego.horse" rel="noopener noreferrer"&gt;diego.horse&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Is any of these metrics relevant to you? Which metric should I dive into next?&lt;/p&gt;

&lt;p&gt;Have a good week filled with no-BS insights.&lt;br&gt;
(っ-,-)つ𐂃&lt;/p&gt;

</description>
      <category>swift</category>
      <category>appstore</category>
      <category>buildinginpublic</category>
      <category>smartkeys</category>
    </item>
    <item>
      <title>No-BS Friday Metrics: Store Conversion Rate</title>
      <dc:creator>Diego Dotta</dc:creator>
      <pubDate>Sat, 01 Feb 2025 01:57:22 +0000</pubDate>
      <link>https://dev.to/diegodotta/no-bs-friday-metrics-store-conversion-rate-35ia</link>
      <guid>https://dev.to/diegodotta/no-bs-friday-metrics-store-conversion-rate-35ia</guid>
      <description>&lt;p&gt;Everyone loves to talk about ASO tricks and how to squeeze every bit of conversion juice from the app store. But what if I told you it doesn’t really matter? Smart Keys store conversion rate is over 50% while the best apps barely scrape 7%. So either I’m a wizard or this is an overrated metric.&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.amazonaws.com%2Fuploads%2Farticles%2Fy4rg9a5nh1bwyap783g0.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.amazonaws.com%2Fuploads%2Farticles%2Fy4rg9a5nh1bwyap783g0.png" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We, builders, makers, indie devs, and friends love the idea that some ASO tweak will be the magic bullet. a better subtitle, the right screenshots, a catchy promo text. Sure, those things help a little, but they won’t move the needle in a meaningful way.&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.amazonaws.com%2Fuploads%2Farticles%2Fni8sieo6hzk3vdt960dz.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.amazonaws.com%2Fuploads%2Farticles%2Fni8sieo6hzk3vdt960dz.png" alt="Image description" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what actually happened here? What’s the big ASO secret? It’s a three-letter word: Ads. No ASO magic tricks, no growth hacks, no overcomplicated strategy. just Ads that work.&lt;/p&gt;

&lt;p&gt;So is this store conversion rate relevant? not really. It looks good on a dashboard, but that’s about it. Focus on what actually drives growth, not vanity metrics that make you feel good but don’t pay the bills.&lt;/p&gt;

&lt;p&gt;That’s it for today. Next Friday, I’ll dive into retention, the real deal.&lt;/p&gt;

&lt;p&gt;Have a no-BS weekend. See ya. ✌️&lt;/p&gt;

</description>
      <category>smartkeys</category>
      <category>analytics</category>
      <category>buildinpublic</category>
      <category>ios</category>
    </item>
  </channel>
</rss>
