<?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: superfire</title>
    <description>The latest articles on DEV Community by superfire (@superfire).</description>
    <link>https://dev.to/superfire</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%2F4163957%2F45a2c506-f139-48e3-a61d-44d11ce802d7.jpg</url>
      <title>DEV Community: superfire</title>
      <link>https://dev.to/superfire</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/superfire"/>
    <language>en</language>
    <item>
      <title>Search engines saw 4 syllables. The page had 199. Here's the bug.</title>
      <dc:creator>superfire</dc:creator>
      <pubDate>Sat, 17 Oct 2026 04:47:51 +0000</pubDate>
      <link>https://dev.to/superfire/search-engines-saw-4-syllables-the-page-had-199-heres-the-bug-59a4</link>
      <guid>https://dev.to/superfire/search-engines-saw-4-syllables-the-page-had-199-heres-the-bug-59a4</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article was created with the help of AI and reviewed line by line by the author. Every number below was verified against the running site.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A pinyin chart is a table of roughly 400 syllables. The one I maintain had 199 of them in its data file.&lt;/p&gt;

&lt;p&gt;Both numbers were true. Bing agreed with the first one and disagreed with the second.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug we shipped
&lt;/h2&gt;

&lt;p&gt;The page rendered its table at runtime. The HTML that a crawler fetched contained an empty table element: a &lt;code&gt;table&lt;/code&gt; tag with the class &lt;code&gt;pc-grid&lt;/code&gt; and nothing between its tags.&lt;/p&gt;

&lt;p&gt;Everything below that point (19 initials, 199 syllables, the four-tone grid) lived inside a JavaScript object called &lt;code&gt;SIMPLE&lt;/code&gt;. The code was correct. It just did not exist in the document.&lt;/p&gt;

&lt;p&gt;Strip the script tags from the served page and you can read four syllables in its text content. Four.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the numbers said
&lt;/h2&gt;

&lt;p&gt;Bing Webmaster Tools, three-month window. One page, 101 impressions, 0 clicks, average position 6.&lt;/p&gt;

&lt;p&gt;We had assumed this was a copy problem for weeks. Title, description, the promise in the H1, all of it fine. A page sitting at position 6 for its main query with zero clicks out of 101 impressions usually means one thing: the searcher arrives expecting a chart, finds an empty box while the script boots, and leaves before it paints.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;Pre-render the data into the markup at build time. Keep the JavaScript for the click handler, drop it from the rendering job.&lt;/p&gt;

&lt;p&gt;The build step walks the same data structure the client script would have walked, and writes each syllable into a table cell as plain HTML. The served document now exposes 374 syllable cells to a crawler, and the page still plays audio on click because the JavaScript never went anywhere.&lt;/p&gt;

&lt;p&gt;Same treatment on four more pages in one pass (tone comparison, name generator, stroke order rules, number hand gestures). One rule held throughout: if the content is the point of the page, it cannot live behind a script tag.&lt;/p&gt;

&lt;p&gt;The page in question is &lt;a href="https://thechinesepath.com/pinyin-chart" rel="noopener noreferrer"&gt;https://thechinesepath.com/pinyin-chart&lt;/a&gt; if you want to check the markup yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that bit us
&lt;/h2&gt;

&lt;p&gt;The obvious version of that script was not idempotent. It ran over five pages, the name generator threw on a missing anchor, and the first four files were already on disk. Re-running wrote them again. One data table ended up with five copies of a row where it should have had three.&lt;/p&gt;

&lt;p&gt;The rule became: dry-run every page first, and if any single one fails, write nothing. Mark what you injected with a token you own, never with something you count in the output, since counting injected markup to decide whether it was injected cannot work.&lt;/p&gt;

&lt;h2&gt;
  
  
  One more thing about reporting
&lt;/h2&gt;

&lt;p&gt;The same project reported "zero backlinks" for nineteen days. The tool returned an empty list every time, so zero went into the notes and stayed there.&lt;/p&gt;

&lt;p&gt;The backlinks existed the whole time. Three links from a DEV post, all live, none of them nofollow. A different endpoint in the same API (one returning an anchor count per URL instead of a list) showed them immediately.&lt;/p&gt;

&lt;p&gt;An empty list is not an empty set. Before writing any number into your notes, check whether your tool is reporting "nothing found" or "nothing searched."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is worth writing down
&lt;/h2&gt;

&lt;p&gt;If you serve a static site and a chunk of your content is generated client-side, run this check today: fetch your own page, strip the script tags, count what is left. If the number is small, you already know why your rankings look flat.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>staticwebapps</category>
    </item>
    <item>
      <title>Show DEV: 25 free Chinese learning tools with no backend, and the honest traffic numbers</title>
      <dc:creator>superfire</dc:creator>
      <pubDate>Mon, 05 Oct 2026 14:41:37 +0000</pubDate>
      <link>https://dev.to/superfire/show-dev-25-free-chinese-learning-tools-with-no-backend-and-the-honest-traffic-numbers-3ddf</link>
      <guid>https://dev.to/superfire/show-dev-25-free-chinese-learning-tools-with-no-backend-and-the-honest-traffic-numbers-3ddf</guid>
      <description>&lt;p&gt;What it is&lt;br&gt;
I built this because I couldn't find a free place to practice the boring parts of Chinese. Typing tones. Getting stroke order right. Knowing which measure word goes with which noun.&lt;br&gt;
It's 46 pages now, and 25 of those are tools or resource pages. The &lt;a href="https://thechinesepath.com/pinyin-chart" rel="noopener noreferrer"&gt;pinyin chart&lt;/a&gt; is the one people use most. The &lt;a href="https://thechinesepath.com/chinese-stroke-order" rel="noopener noreferrer"&gt;stroke order page&lt;/a&gt; animates each character. There's a &lt;a href="https://thechinesepath.com/chinese-transport-simulator" rel="noopener noreferrer"&gt;transport simulator&lt;/a&gt; that runs real airport and subway conversations, plus a hospital one, because those are the two situations where I froze hardest.&lt;br&gt;
All of it is static HTML, CSS, and vanilla JS. No backend, no database, no login page. The audio is the browser's own speech synthesis. I call it that instead of dressing it up as an AI tutor.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the traffic looks
&lt;/h3&gt;

&lt;p&gt;I'd rather post the real numbers than a win story.&lt;/p&gt;

&lt;p&gt;Eight days of Cloudflare data: 93 page views, 71 sessions, 66 of them real humans once I strip the bots. About one visit in nine came from a search engine. Zero backlinks.&lt;/p&gt;

&lt;p&gt;That last number is the one that matters and it's the one I can't buy.&lt;/p&gt;

&lt;p&gt;Ranking on Google is out of reach from where I build, so I'm working Bing, which is maybe a tenth of the English market. What gets indexed, gets indexed slowly.&lt;/p&gt;

&lt;p&gt;One thing did catch me off guard. A ChatGPT share link turned up as a referrer. Somebody pasted a page into a conversation and clicked through. It's nofollow, so it earns no ranking credit, but it means the content is reaching people somehow.&lt;/p&gt;

&lt;p&gt;Three weeks in, mobile was at 50% of sessions for a day. Four countries, all phones.&lt;/p&gt;

&lt;p&gt;People learn Chinese on the bus, not at a desk.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's next
&lt;/h3&gt;

&lt;p&gt;The 500-phrase PDF is the only paid thing, at $9.90. Everything else stays free.&lt;/p&gt;

&lt;p&gt;If you've run a domain with no backlinks and no traffic, I'd like to hear what moved the needle for you.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>learning</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
