<?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: Daniel Mercer</title>
    <description>The latest articles on DEV Community by Daniel Mercer (@danielmercer).</description>
    <link>https://dev.to/danielmercer</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%2F4186020%2F5faef3a0-a3e9-4cce-8029-00c662efc658.png</url>
      <title>DEV Community: Daniel Mercer</title>
      <link>https://dev.to/danielmercer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/danielmercer"/>
    <language>en</language>
    <item>
      <title>Why 27,854 route pages need a different sitemap strategy</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Wed, 04 Nov 2026 07:02:41 +0000</pubDate>
      <link>https://dev.to/danielmercer/why-27854-route-pages-need-a-different-sitemap-strategy-4jp1</link>
      <guid>https://dev.to/danielmercer/why-27854-route-pages-need-a-different-sitemap-strategy-4jp1</guid>
      <description>&lt;p&gt;When a site grows to 27,854 route pages, the sitemap stops being a formality and becomes a strategy decision. Search engines will not crawl everything equally, so the question is not how to list every page, it is how to tell crawlers which pages matter, which pages are new, and which pages can wait.&lt;/p&gt;

&lt;p&gt;The first mistake we made was one giant sitemap. It was technically valid and practically useless: it hid the important pages among thousands of near-identical route pages, and when something changed, the whole file had to be regenerated. We split it into smaller sitemaps by route type and by region, so a change to one group only touches that group's file, and the sitemap index tells crawlers exactly where to look.&lt;/p&gt;

&lt;p&gt;The second mistake was treating all routes as equal. A route between two large cities gets searched far more than a route between two small towns, and crawling them equally wastes crawl budget on pages few people want. We now order sitemap entries so the highest-demand routes appear first and are updated most often, while low-demand routes are still listed, just less prominently. This is not hiding pages, it is prioritising attention.&lt;/p&gt;

&lt;p&gt;The third lesson was about freshness signals. A sitemap that claims every page changed yesterday, when nothing changed, teaches crawlers to ignore it. We only update lastmod when a page genuinely changes, price data, content, or structure, and we stopped regenerating timestamps on a schedule. Honest freshness signals get honoured. Noisy ones get ignored.&lt;/p&gt;

&lt;p&gt;The fourth lesson was internal linking. A sitemap alone does not get a page crawled well; links from popular pages do. We added related-route links on every route page, so a crawler arriving at a busy route can walk to neighbouring routes naturally, and a visitor can too. The sitemap opens the door, but internal links do the walking.&lt;/p&gt;

&lt;p&gt;The result is not dramatic, it is steady: the pages that matter get crawled faster, new routes get found sooner, and the long tail still exists for the rare searches that need it. The site is &lt;a href="https://myfastmovers.com" rel="noopener noreferrer"&gt;My Fast Movers&lt;/a&gt;, a long-distance moving cost calculator with a free quote tool, and its 27,854 routes are a reminder that at scale, organisation is a feature, not paperwork.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>nextjs</category>
      <category>data</category>
    </item>
    <item>
      <title>Designing search for 56,000 games: what actually helps players find a game</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Wed, 04 Nov 2026 07:01:24 +0000</pubDate>
      <link>https://dev.to/danielmercer/designing-search-for-56000-games-what-actually-helps-players-find-a-game-5pe</link>
      <guid>https://dev.to/danielmercer/designing-search-for-56000-games-what-actually-helps-players-find-a-game-5pe</guid>
      <description>&lt;p&gt;Running a portal with 56,000 browser games sounds like a search problem, and it is, but not the kind most search advice covers. Players do not arrive with a precise query. They arrive with a mood, ten free minutes, and a vague idea like something relaxing or something with cars. Search that only matches exact titles fails them, because they do not know the titles yet.&lt;/p&gt;

&lt;p&gt;The first lesson was that categories matter more than keywords. A player who clicks puzzle games is not searching, they are browsing with intent, and the category page is the search result. We rebuilt category pages to load instantly, show the most played games first, and keep the filters visible, so a player can narrow from puzzle to word puzzle to crossword in two clicks without typing anything.&lt;/p&gt;

&lt;p&gt;The second lesson was about spelling and synonyms. Players type car game, cars, racing, and driving for the same thing, and a search that treats those as different queries returns different results for the same intent. We added a small synonym map for the most common terms, built from our own search logs, not from a generic thesaurus. It is boring work and it made the biggest difference: the share of searches that returned zero useful results fell sharply once synonyms were handled.&lt;/p&gt;

&lt;p&gt;The third lesson was speed over cleverness. A search box that suggests results as you type feels modern, but on a low-end phone on a slow connection it feels broken, because suggestions arrive after the player has already pressed enter. We made search server-rendered and fast first, then added suggestions only where they did not slow the first result. Players forgive a plain search box. They do not forgive a slow one.&lt;/p&gt;

&lt;p&gt;The fourth lesson was that recency is a trap. Sorting by newest fills the page with games nobody has played, while sorting by most played fills it with the same ten games forever. We settled on a blend: proven games at the top, a rotating set of less-played games below, so discovery keeps happening without the page turning into a graveyard of untested titles.&lt;/p&gt;

&lt;p&gt;None of this required machine learning or a search vendor. It required watching real searches, fixing the top twenty failed queries, and repeating that every month. The full catalogue is at &lt;a href="https://gameziko.com" rel="noopener noreferrer"&gt;GameZiko&lt;/a&gt;, where you can play free browser games with no download and no sign-up, and the search box is the simplest thing on the page, which is exactly how it should be.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>javascript</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>The quote gap: why the cheapest moving quote is rarely the cheapest move</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Tue, 03 Nov 2026 07:02:45 +0000</pubDate>
      <link>https://dev.to/danielmercer/the-quote-gap-why-the-cheapest-moving-quote-is-rarely-the-cheapest-move-4an8</link>
      <guid>https://dev.to/danielmercer/the-quote-gap-why-the-cheapest-moving-quote-is-rarely-the-cheapest-move-4an8</guid>
      <description>&lt;p&gt;We run a moving cost calculator that has priced 27,854 routes, and the most common complaint we hear is not that moving is expensive. It is that the quote a customer accepted was not the price they paid. The gap between quote and final bill is where most moving misery lives, and it is usually explainable before anyone signs anything.&lt;/p&gt;

&lt;p&gt;The first cause is scope. A quote that covers loading, transport and unloading sounds complete, but the expensive parts of a move often sit outside those words: stairs, long carries from truck to door, packing materials, disassembly and reassembly, storage between homes. A quote that omits them is not cheaper, it is incomplete, and the missing items reappear on moving day at the worst possible moment, when you cannot shop around.&lt;/p&gt;

&lt;p&gt;The second cause is weight versus volume. Long-distance moves are usually priced on weight or on cubic feet, and the two methods give different answers for the same household. A home full of books is heavy but compact; a home full of light furniture is bulky but light. A quote that does not say which method it uses cannot be compared with one that does, and comparing two quotes priced on different bases is how the cheapest-looking option wins and then loses.&lt;/p&gt;

&lt;p&gt;The third cause is the estimate type. A non-binding estimate can move, legally, and it usually moves up. A binding estimate cannot, provided the inventory does not change. Customers who choose on price alone usually choose a non-binding estimate, because it looks lower, and then discover the difference when the truck is weighed. The binding quote that looked expensive was often the honest one.&lt;/p&gt;

&lt;p&gt;None of this means movers are dishonest. It means quotes are documents with fine print, and the fine print is where the price lives. The questions that close the gap are simple: is this binding or non-binding, priced on weight or volume, and does it include stairs, long carries, packing and storage? A mover who answers all four clearly is usually a mover you can trust, whatever the number.&lt;/p&gt;

&lt;p&gt;We built our calculator to answer the price question before the fine print matters: a free long-distance estimate at My Fast Movers, with no address form required: &lt;a href="https://myfastmovers.com" rel="noopener noreferrer"&gt;https://myfastmovers.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>product</category>
      <category>data</category>
      <category>ux</category>
    </item>
    <item>
      <title>What our most-played games have in common (and what that taught us about discovery)</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Tue, 03 Nov 2026 07:01:59 +0000</pubDate>
      <link>https://dev.to/danielmercer/what-our-most-played-games-have-in-common-and-what-that-taught-us-about-discovery-39nc</link>
      <guid>https://dev.to/danielmercer/what-our-most-played-games-have-in-common-and-what-that-taught-us-about-discovery-39nc</guid>
      <description>&lt;p&gt;GameZiko hosts more than 56,000 free browser games. Every month, a small handful of them take most of the plays, and for a long time I assumed the winners were simply the best games. After looking at the actual play data, the pattern turned out to be more interesting, and more useful, than "good games win".&lt;/p&gt;

&lt;p&gt;The first thing the most-played games share is a fast first minute. The top games are playable within seconds of the page loading, with no tutorial, no account, and no decision more complicated than "click here to start". Games that need three minutes of explanation before the fun starts rarely recover, no matter how good they become later. Players do not quit because a game is bad; they quit because the first minute did not convince them to spend a second one.&lt;/p&gt;

&lt;p&gt;The second pattern is replayability in small doses. The most-played games are almost all games you can finish, or meaningfully progress in, within five to ten minutes. A puzzle with one more round, an arcade game with one more high score to chase, a card game with one more hand. Short sessions fit into real life: a lunch break, a bus ride, a wait for a kettle to boil. Games that demand an hour of uninterrupted attention get bookmarked and forgotten.&lt;/p&gt;

&lt;p&gt;The third pattern surprised me most: the winners are rarely the newest games. Discovery on a huge catalogue is hard, and players trust what other players already play. A game with a visible play count and a familiar name gets clicked, and every click makes it more visible. New games, however good, start invisible and stay invisible unless something surfaces them. That is a discovery problem, not a quality problem, and it changed how we think about the catalogue.&lt;/p&gt;

&lt;p&gt;So we changed what we surface. Instead of sorting purely by popularity, which only reinforces the winners, we started rotating a "worth a try" selection of strong but underplayed games onto the homepage, chosen by hand, not by algorithm. The result was measurable: games in the rotation saw several times their usual plays, and a few of them stayed popular after the rotation ended, because players who found them kept coming back.&lt;/p&gt;

&lt;p&gt;The lesson generalises beyond games. On any large catalogue, popularity is a lagging indicator of discovery, not a pure measure of quality, and a small amount of human curation beats a purely algorithmic sort. If you run a content site of any size, look at what your top ten have in common, and then ask whether the pattern is quality, or just visibility wearing quality's clothes.&lt;/p&gt;

&lt;p&gt;You can see the catalogue for yourself at GameZiko, where every game is free, with no download and no sign-up: &lt;a href="https://gameziko.com" rel="noopener noreferrer"&gt;https://gameziko.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>indiedev</category>
      <category>performance</category>
      <category>discovery</category>
    </item>
    <item>
      <title>Why moving quotes differ by thousands for the same route</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Mon, 02 Nov 2026 07:05:47 +0000</pubDate>
      <link>https://dev.to/danielmercer/why-moving-quotes-differ-by-thousands-for-the-same-route-4n32</link>
      <guid>https://dev.to/danielmercer/why-moving-quotes-differ-by-thousands-for-the-same-route-4n32</guid>
      <description>&lt;p&gt;Ask three movers to price the same long-distance move and you will often get three numbers thousands apart, which makes customers understandably suspicious. Somebody must be lying, right? Usually, nobody is. The quotes differ because the movers are not actually pricing the same thing, even when the route looks identical.&lt;/p&gt;

&lt;p&gt;The first difference is what counts as the move. One quote may cover loading, transport and unloading only, while another includes packing materials, furniture disassembly, and a month of storage that the customer never asked for but also never declined. Comparing headline numbers without comparing inclusions is like comparing the price of a car with the price of a car plus insurance, fuel and servicing.&lt;/p&gt;

&lt;p&gt;The second difference is weight versus volume. Long-distance pricing is usually weight-based, but weight is estimated, not measured, until moving day, and estimators disagree honestly about how much a household weighs. A three-bedroom house can plausibly be estimated anywhere from 7,000 to 10,000 pounds, and that range alone explains a large part of the price gap.&lt;/p&gt;

&lt;p&gt;The third difference is timing. A mover with a truck already going your way can price sharply, while a mover who must send a truck out empty charges for the empty leg too. Season matters as well: summer quotes run higher because demand runs higher, and a flexible date can be worth real money.&lt;/p&gt;

&lt;p&gt;The fourth difference is the estimate type. A non-binding estimate can change on moving day when the actual weight is known, while a binding estimate locks the price but usually starts higher to cover the mover's risk. Neither is dishonest, but they are not comparable numbers, and customers who compare them directly will always feel misled.&lt;/p&gt;

&lt;p&gt;The practical advice is simple: ask every mover for the same written breakdown, same inclusions, same estimate type, same date window, and then compare. And before you call anyone, get a rough independent number first: the free calculator at &lt;a href="https://myfastmovers.com" rel="noopener noreferrer"&gt;https://myfastmovers.com&lt;/a&gt; estimates long-distance moving costs from route data, which gives you a baseline to judge every quote against. If a quote lands far from that baseline, you now know which questions to ask, and that is worth more than any single number.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>product</category>
      <category>data</category>
      <category>ux</category>
    </item>
    <item>
      <title>How we serve 56,000 game pages from a single static build</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Mon, 02 Nov 2026 07:04:14 +0000</pubDate>
      <link>https://dev.to/danielmercer/how-we-serve-56000-game-pages-from-a-single-static-build-4ok</link>
      <guid>https://dev.to/danielmercer/how-we-serve-56000-game-pages-from-a-single-static-build-4ok</guid>
      <description>&lt;p&gt;When people hear that GameZiko lists more than 56,000 browser games, they usually picture a huge database, a fleet of servers, and a team keeping it all running. The reality is much simpler, and deliberately so: the whole catalogue is served from a single static build. No database queries at request time, no per-page server rendering, just files on a CDN. Here is why that choice works, and where it bites.&lt;/p&gt;

&lt;p&gt;The first reason is speed under load. A game page is mostly the same for every visitor: the title, the description, the embed, and the surrounding navigation. Generating that page fresh for each visitor would burn server time on work that never changes, while a prebuilt file is served in milliseconds by a CDN edge node near the visitor. When a game suddenly gets popular, nothing has to scale, because the file was already there.&lt;/p&gt;

&lt;p&gt;The second reason is cost. A static build means the hosting bill stays flat no matter how many pages exist, because storage is cheap and bandwidth is the only variable. A database-backed catalogue, by contrast, grows more expensive with every page and every query, and the bill arrives whether or not the traffic does. For a free site with no sign-ups and no paywall, keeping the bill boring is a survival strategy, not a preference.&lt;/p&gt;

&lt;p&gt;The third reason is reliability. There is no database to go down, no connection pool to exhaust, and no query that gets slower as the catalogue grows. If the build succeeds, the site works, and if a deploy goes wrong, the previous build is still there to roll back to. That simplicity is worth more than any feature a dynamic stack would add.&lt;/p&gt;

&lt;p&gt;The trade-offs are real, though. Every change, even a typo fix on one page, means rebuilding the whole catalogue, which takes time and discipline. Search and filtering have to happen in the browser or through a prebuilt index, not through a database query, and anything genuinely personal, like saved favourites, has to live in the visitor's own browser, not on our servers.&lt;/p&gt;

&lt;p&gt;The lesson we keep relearning is that boring infrastructure is a feature. A single static build will never be the most exciting architecture, but it serves 56,000 pages quickly, cheaply and reliably, and for a free games portal, that is the whole job. You can play the games themselves at &lt;a href="https://gameziko.com" rel="noopener noreferrer"&gt;https://gameziko.com&lt;/a&gt;, no download and no sign-up needed, which is exactly how a static site should feel: instant, and invisible.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>javascript</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>How we handle quote requests for routes we have never priced</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Sun, 01 Nov 2026 07:26:41 +0000</pubDate>
      <link>https://dev.to/danielmercer/how-we-handle-quote-requests-for-routes-we-have-never-priced-3fhk</link>
      <guid>https://dev.to/danielmercer/how-we-handle-quote-requests-for-routes-we-have-never-priced-3fhk</guid>
      <description>&lt;p&gt;My Fast Movers publishes cost estimates for 27,854 long-distance moving routes. That number sounds comprehensive until a user types in a route we have not published, and then the honest answer is that we do not have a specific number for that pair of places. How we handle that moment matters more than the size of the catalogue.&lt;/p&gt;

&lt;p&gt;The first rule is never to invent a precise-looking number. A quote calculator that returns a confident figure for a route it has never priced is lying with formatting, and users can feel it when the real quotes arrive wildly different. So for an unpriced route, we show a range built from the nearest comparable routes: similar distance, similar region, similar home size, with the comparison explained in plain language next to the number.&lt;/p&gt;

&lt;p&gt;The second rule is to say what the range is made of. A range without an explanation is just a vaguer lie, so the page shows the distance band, the home-size assumptions and the factors that move a real quote up or down: stairs, long carries, packing help and timing. A user who understands why the range is wide trusts it more than a user handed a single number with no workings.&lt;/p&gt;

&lt;p&gt;Under the hood, the fallback is a distance-and-size model, not a lookup. We take the mileage, apply the per-mile cost curve fitted from our priced routes, adjust for home size, and widen the band as the route gets further from anything we have actually priced. The further the extrapolation, the wider the band and the clearer the warning. Precision that is not earned is worse than a wide range that is honest.&lt;/p&gt;

&lt;p&gt;We also log every unpriced-route request, anonymised, and those logs decide what gets priced next. A route requested fifty times in a month jumps the queue for proper pricing, because demand is the best evidence of what the catalogue is missing. The catalogue grows in the direction users actually travel, not the direction we guessed.&lt;/p&gt;

&lt;p&gt;The lesson generalises beyond moving. Any estimator, pricing tool or calculator will meet inputs it was not built for, and the choice is always the same: fake precision, or an honest range with its workings shown. We chose the range, and our users have rewarded us for it.&lt;/p&gt;

&lt;p&gt;You can try the calculator yourself at My Fast Movers, where long-distance moving costs are estimated without an address form: &lt;a href="https://myfastmovers.com" rel="noopener noreferrer"&gt;https://myfastmovers.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>product</category>
      <category>data</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Why our game pages have no login wall, and what that costs us in analytics</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Sun, 01 Nov 2026 07:25:23 +0000</pubDate>
      <link>https://dev.to/danielmercer/why-our-game-pages-have-no-login-wall-and-what-that-costs-us-in-analytics-4g88</link>
      <guid>https://dev.to/danielmercer/why-our-game-pages-have-no-login-wall-and-what-that-costs-us-in-analytics-4g88</guid>
      <description>&lt;p&gt;Every game page on GameZiko loads the same way: open the link, play the game. There is no account, no sign-up form, no "continue with Google" button standing between a player and a game. That was a deliberate choice, and it is one we revisit every time someone asks why our analytics look so thin.&lt;/p&gt;

&lt;p&gt;The obvious benefit is conversion, if you can call it that. A player who clicks a game link and hits a login wall bounces. A player who clicks and is playing within two seconds stays. For a catalogue of 56,000 browser games, most of which are discovered through a search result or a shared link, removing friction matters more than collecting email addresses we would never use well.&lt;/p&gt;

&lt;p&gt;The cost is real, though. Without accounts, we cannot tell a returning player from a new one with any confidence. We cannot build a "your recently played games" list that survives a cleared cache, and we cannot send a "come back" email to someone who drifted away. Our analytics are aggregate shapes, not user journeys: which categories get played, which games hold attention, which pages load slowly. That is enough to run the site, but it is not enough to run a growth team, and we have made peace with that.&lt;/p&gt;

&lt;p&gt;There are technical upsides that people forget. No login wall means no session handling on game pages, no authentication round trip before the game embed loads, and no personal data to protect on those pages. Our game pages stay light, which is part of why they work on old phones and slow connections. The page is a game, a description and a handful of links, and nothing else needs to happen before play starts.&lt;/p&gt;

&lt;p&gt;We do track what we can without identifying anyone: which games are started, which are finished, and where players drop off. That tells us more about game quality than a user profile would. A game that everyone abandons in thirty seconds has a problem, whatever its category, and a game that players return to three days later is doing something right, even if we never learn who those players are.&lt;/p&gt;

&lt;p&gt;Would a login wall earn us more? Probably, in the narrow sense of owning an audience we could email. But it would cost us the thing players actually value about the site: that it just works, instantly, with nothing asked in return. For a free games portal, that trade is not worth making.&lt;/p&gt;

&lt;p&gt;If you want to see the result, GameZiko has thousands of free browser games that open and play instantly, with no download and no sign-up: &lt;a href="https://gameziko.com" rel="noopener noreferrer"&gt;https://gameziko.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>performance</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>How we test quote accuracy without real customer moves</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Sat, 31 Oct 2026 07:04:24 +0000</pubDate>
      <link>https://dev.to/danielmercer/how-we-test-quote-accuracy-without-real-customer-moves-gj6</link>
      <guid>https://dev.to/danielmercer/how-we-test-quote-accuracy-without-real-customer-moves-gj6</guid>
      <description>&lt;p&gt;A moving cost calculator has a testing problem. You cannot run a real move every time you change the pricing logic, and you cannot ask real customers to be your test cases. So we test quote accuracy without real moves, using a set of invented moves that cover the cases real moves actually produce.&lt;/p&gt;

&lt;p&gt;First, we build a library of test moves. A studio flat moving one state over. A four-bedroom house moving cross-country. A move with stairs at both ends, a move with a long carry from the truck to the door, a move with a piano, and a move with nothing unusual at all. Each test move has an expected price range, agreed in advance, so a change that moves a quote outside that range fails loudly instead of slipping through.&lt;/p&gt;

&lt;p&gt;Second, we test the edges, not just the averages. The average move is easy to price. The moves that break calculators are the odd ones: a very short move that still needs a full crew, a very long move with a small load, a move in the cheapest month versus the most expensive month. If the calculator handles the edges sensibly, the middle takes care of itself.&lt;/p&gt;

&lt;p&gt;Third, we test what the form does not ask. Our calculator deliberately does not ask for an address, so it must estimate from distance, home size and a few honest inputs. That means testing what happens when a visitor leaves a field blank, picks an unusual combination, or changes one answer halfway through. A calculator that breaks on an unusual answer is worse than a calculator that admits uncertainty.&lt;/p&gt;

&lt;p&gt;Fourth, we compare quotes over time. Every time we change the pricing model, we run the same test moves through the old and new versions and look at the difference. A change that moves most quotes by a small amount is probably fine. A change that moves a few quotes by a huge amount needs an explanation before it ships.&lt;/p&gt;

&lt;p&gt;What still breaks? Real moves are messier than test moves. A customer always has one more item, one more flight of stairs, or one more constraint that no test case captured. So we treat test moves as a safety net, not a guarantee, and we watch real quote patterns for surprises the tests missed.&lt;/p&gt;

&lt;p&gt;The lesson is simple: you do not need real customers to test a calculator, but you do need realistic cases, honest expected ranges, and a comparison step before every release. If you build a pricing tool, build its test moves first. They are the cheapest moves you will ever run.&lt;/p&gt;

&lt;p&gt;You can see the result at My Fast Movers, a long-distance moving cost calculator that works without an address form: &lt;a href="https://myfastmovers.com" rel="noopener noreferrer"&gt;https://myfastmovers.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>product</category>
      <category>data</category>
      <category>testing</category>
    </item>
    <item>
      <title>How we keep game thumbnails fast when a page lists hundreds of games</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Sat, 31 Oct 2026 07:03:03 +0000</pubDate>
      <link>https://dev.to/danielmercer/how-we-keep-game-thumbnails-fast-when-a-page-lists-hundreds-of-games-1fap</link>
      <guid>https://dev.to/danielmercer/how-we-keep-game-thumbnails-fast-when-a-page-lists-hundreds-of-games-1fap</guid>
      <description>&lt;p&gt;A game portal page that lists hundreds of games has a thumbnail problem. Each thumbnail is small, but hundreds of small images add up to a page that feels heavy, especially on a phone or a slow connection. The fix is not one trick. It is a set of small decisions that keep the page light even when the catalogue behind it is huge.&lt;/p&gt;

&lt;p&gt;First, we never load all the thumbnails at once. Only the images near the top of the page load immediately. The rest wait until the visitor scrolls near them. This is lazy loading, and it is the single biggest win, because most visitors never scroll through an entire list of hundreds of games. Loading images for games nobody sees is pure waste.&lt;/p&gt;

&lt;p&gt;Second, we keep thumbnails small on purpose. A thumbnail displayed at a few hundred pixels wide does not need a full-size image. We serve a version sized for the display, in a modern format where the browser supports it, and we let older browsers fall back gracefully. A thumbnail that is a tenth of the size loads a tenth as fast, and nobody can tell the difference at that size.&lt;/p&gt;

&lt;p&gt;Third, we reserve the space before the image arrives. Without a reserved size, each image pushes the page around as it loads, and the layout jumps under the visitor's finger. Setting the width and height in advance keeps the grid stable, so a visitor can tap a game without the page shifting at the last second.&lt;/p&gt;

&lt;p&gt;Fourth, we treat the thumbnail as a promise, not a decoration. A blurry or misleading thumbnail makes a visitor bounce, and a bounce costs more than a slow load. So we pick thumbnails that show the actual game, not a generic splash screen, and we keep them consistent in size and style so the grid is easy to scan.&lt;/p&gt;

&lt;p&gt;What still breaks? Caching, as always. A game that changes its artwork can keep showing the old thumbnail until the cache catches up, so changed images get a new path rather than overwriting the old one. And a page with hundreds of games still needs a sensible limit: we paginate long lists, because no visitor benefits from a page that never ends.&lt;/p&gt;

&lt;p&gt;None of this is glamorous. Lazy loading, right-sized images, stable layouts and honest thumbnails will carry a huge catalogue further than any clever image pipeline. If you run a content-heavy site, start with the boring choices. They are boring because they work.&lt;/p&gt;

&lt;p&gt;You can see the result at GameZiko, a free browser games portal with 56,000+ HTML5 games, no downloads and no sign-ups: &lt;a href="https://gameziko.com" rel="noopener noreferrer"&gt;https://gameziko.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>javascript</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>What moving quote forms get wrong about stairs, elevators and long carries</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Fri, 30 Oct 2026 07:07:41 +0000</pubDate>
      <link>https://dev.to/danielmercer/what-moving-quote-forms-get-wrong-about-stairs-elevators-and-long-carries-2mji</link>
      <guid>https://dev.to/danielmercer/what-moving-quote-forms-get-wrong-about-stairs-elevators-and-long-carries-2mji</guid>
      <description>&lt;p&gt;Most moving quote forms ask two questions: how big is your home, and how far are you moving? Those matter, but they miss the details that decide whether moving day takes four hours or eight. Stairs, elevators, long carries and tight doorways are where estimates go wrong, and they are exactly the details a good form should ask about before anyone talks price.&lt;/p&gt;

&lt;p&gt;Start with stairs. A third-floor walk-up is a different job from a ground-floor flat with the same number of rooms. Every flight adds carries, rest breaks and risk, especially for mattresses, wardrobes and appliances. A form that asks only for bedroom count treats both jobs as identical, and the crew finds out the truth on arrival. Asking "how many flights of stairs, at each end?" is a small question that prevents a large surprise.&lt;/p&gt;

&lt;p&gt;Elevators are subtler. An elevator helps, but only if it is reserved, large enough and available for the whole job. A small passenger lift that fits one wardrobe at a time is barely faster than stairs, and a building that requires the lift to be booked in a two-hour window creates a hard deadline for the whole move. A good form asks whether there is an elevator, whether it needs booking, and whether it fits large furniture. "Yes, there is a lift" is not enough information.&lt;/p&gt;

&lt;p&gt;Then there is the long carry: the distance from the truck to the front door. A home with a long driveway, a gated complex or a loading bay far from the entrance adds dozens of trips, each one carrying weight across open ground. In bad weather or summer heat, that distance also decides how fast a crew can safely work. Forms rarely ask about it, and customers rarely think to mention it, because the distance feels normal to them. It is only normal until you carry a sofa across it twenty times.&lt;/p&gt;

&lt;p&gt;Doorways, turns and parking matter in the same way. A sofa that fits through a door with an inch to spare is fine; a sofa that needs a door removed from its hinges is a different job. Street parking versus a loading dock decides how far the truck can get, which feeds straight back into the long carry. None of these are exotic situations. They are ordinary homes, and ordinary homes are where estimates fail.&lt;/p&gt;

&lt;p&gt;So why do forms skip them? Because every extra question costs completions. A form with twenty fields converts worse than a form with five, and product teams know it. The answer is not to ask everything up front, but to ask the high-impact questions in plain language and to explain why each one matters. "How many flights of stairs?" with a one-line note saying stairs change the time estimate will get honest answers. A bare dropdown labelled "Access" will not.&lt;/p&gt;

&lt;p&gt;Our approach on My Fast Movers is to estimate from route and home size first, keep personal details out of the calculator, and treat access as a clearly labelled adjustment rather than a surprise fee discovered on moving day. The estimate is honest about what it includes and what can change it, and that honesty matters more than false precision. A quote that says "about this much, and here is what would change it" is more useful than a quote that pretends to know to the dollar.&lt;/p&gt;

&lt;p&gt;If you build quote or booking forms, audit them for the access questions. Stairs, elevator booking, carry distance, parking and the largest awkward item are five questions that will improve your estimates more than any redesign of the price display. Your customers already know the answers. The form just has to ask.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://myfastmovers.com" rel="noopener noreferrer"&gt;My Fast Movers&lt;/a&gt; is a long-distance moving cost calculator and route directory, with a free estimate tool that works without an address form.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>product</category>
      <category>ux</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Serving 56,000 game pages without a database meltdown: the boring caching choices that work</title>
      <dc:creator>Daniel Mercer</dc:creator>
      <pubDate>Fri, 30 Oct 2026 07:06:04 +0000</pubDate>
      <link>https://dev.to/danielmercer/serving-56000-game-pages-without-a-database-meltdown-the-boring-caching-choices-that-work-1oib</link>
      <guid>https://dev.to/danielmercer/serving-56000-game-pages-without-a-database-meltdown-the-boring-caching-choices-that-work-1oib</guid>
      <description>&lt;p&gt;Running a browser games portal with more than 56,000 game pages teaches you one lesson fast: the interesting engineering is not the game itself, it is everything around it. A game page is small. Fifty-six thousand of them, requested in unpredictable spikes whenever a game gets shared, is a different problem. The choices that kept our site stable are boring, and that is exactly why they work.&lt;/p&gt;

&lt;p&gt;First, treat game pages as static content. A game listing does not change every minute. Its title, description and category are stable, and the game file itself changes rarely. So we serve pages that are built ahead of time rather than assembled from a database on every request. The database still exists, but it is not in the hot path for a normal page view. When a page does not need fresh data, do not ask the database for it. That single decision removes the most common failure mode for a content-heavy site: a traffic spike turning into a database queue.&lt;/p&gt;

&lt;p&gt;Second, load the game only when the visitor asks for it. A game file can be far larger than the page around it, and loading it eagerly for every visitor wastes bandwidth and slows the first paint. Our pages load the light shell first: title, description, thumbnail and controls. The game itself starts when the visitor presses play. Visitors who are just browsing never pay the cost of a game they never play, and visitors who do play get a page that already feels fast.&lt;/p&gt;

&lt;p&gt;Third, cache aggressively and invalidate deliberately. Static pages, thumbnails and game files all carry long cache lifetimes, served through a CDN so repeat visits and nearby visitors do not all hit the origin. The trade-off is staleness: when a game file or description changes, the old version can linger. We handle that by versioning changed assets rather than clearing the whole cache. A new game file gets a new path, so old pages keep working and new pages pick up the new file immediately. Blanket cache purges are a last resort, not a routine.&lt;/p&gt;

&lt;p&gt;Fourth, keep the page itself light. This is the least glamorous work and the most valuable. Every script, tracker and widget on a game page competes with the game for the visitor's device, and many of our visitors play on modest hardware or phones. We keep our own page code small, defer anything that is not needed for the first view, and test pages on a low-end device, not just a fast developer machine. A page that feels instant on a flagship phone and sluggish on a three-year-old phone is not a fast page.&lt;/p&gt;

&lt;p&gt;Fifth, skip accounts where accounts add nothing. Our games need no sign-up and no download, and that is a product choice as much as a technical one. No login system means no session database, no password resets and no account-related failure modes on the critical path. Visitors play immediately, and the site has fewer moving parts to break. Accounts make sense for saved progress and social features, but they are not free, and a portal that does not need them should not pay for them.&lt;/p&gt;

&lt;p&gt;What still breaks? Cache invalidation, as always. A changed game that keeps serving the old file is the bug we watch for most, and it is usually a versioning mistake, not a traffic problem. The other recurring issue is a single popular game swamping one cache node, which is a reminder that even a good cache needs monitoring. We watch for sudden spikes per game, not just total traffic, because one viral game behaves very differently from steady growth across the catalogue.&lt;/p&gt;

&lt;p&gt;None of this is novel, and that is the point. Static pages, lazy loading, long caches with versioned assets, light pages and fewer moving parts will carry a large catalogue further than any clever real-time architecture. If you run a content-heavy site, start with the boring choices. They are boring because they have already survived everyone else's traffic spikes, including ours.&lt;/p&gt;

&lt;p&gt;You can see the result at &lt;a href="https://gameziko.com" rel="noopener noreferrer"&gt;GameZiko&lt;/a&gt;, a free browser games portal with 56,000+ HTML5 games, no downloads and no sign-ups.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>javascript</category>
      <category>indiedev</category>
    </item>
  </channel>
</rss>
