<?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: Declan</title>
    <description>The latest articles on DEV Community by Declan (@buildittheywillcome).</description>
    <link>https://dev.to/buildittheywillcome</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%2F4080417%2F6234aad3-9d57-4cd3-a0d1-916f9a1fff03.jpg</url>
      <title>DEV Community: Declan</title>
      <link>https://dev.to/buildittheywillcome</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/buildittheywillcome"/>
    <language>en</language>
    <item>
      <title>The page was Fixed. Here's what I did.</title>
      <dc:creator>Declan</dc:creator>
      <pubDate>Tue, 25 Aug 2026 21:21:49 +0000</pubDate>
      <link>https://dev.to/buildittheywillcome/the-page-was-fixed-heres-what-i-did-2m35</link>
      <guid>https://dev.to/buildittheywillcome/the-page-was-fixed-heres-what-i-did-2m35</guid>
      <description>&lt;p&gt;I build &lt;a href="https://repertoire-builder.com/repertoire-packs.html?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=packs-devto-0825" rel="noopener noreferrer"&gt;repertoire-builder.com&lt;/a&gt; solo. It reads your real Lichess game history and finds the specific opening positions costing you rating, by position rather than by opening name, because "you're bad at the Sicilian" is way less useful than "you keep losing from this exact structure on move 7."&lt;/p&gt;

&lt;p&gt;The core tool is free. No signup, no paid tier on the analysis. That part isn't changing and this post isn't about it.&lt;/p&gt;

&lt;p&gt;This post is about the one page on the site that asks for money, and the fix that shipped today.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;There's a $9 one-time optional add-on called a pack, one per rating band and color. The pack doesn't measure anything new. Line straight off the page: "Nothing new gets measured for a pack - the difference is what you're holding once you've bought one." It takes the same free analysis and turns it into something you can actually sit down and study: one PGN file pruned to just the lines worth memorizing, a printable study guide, and a file that loads straight into the site's own drill trainer.&lt;/p&gt;

&lt;p&gt;The problem was the page itself. Until today, it described all that in words and then asked for $9. You couldn't see a single actual line before paying. I was effectively asking a stranger to trust me blind, on a site they maybe found ten minutes ago, from a builder they've never heard of. I wouldn't pay that. Idk why I expected anyone else to.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Shipped Today
&lt;/h2&gt;

&lt;p&gt;Two things, both live on the redesigned page now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. A real Preview with Real Data.&lt;/strong&gt; Pick a rating band and the page shows you an actual move-by-move line from that pack, with the usage stats baked in. Not a mockup, not "example data." For one band/color combo it's showing &lt;code&gt;e5 → Nc3, 53.5% score (n=2,404)&lt;/code&gt; right now. That's the same kind of line you'd be buying, shown before you've paid anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A Genuine Free Sample.&lt;/strong&gt; You can download the first 47 lines of a pack, no payment, no email, nothing. Then decide about the $9 with the actual product partly in hand.&lt;/p&gt;

&lt;p&gt;The framing line on the page sums up the whole split: &lt;strong&gt;"Free tells you what to play. The pack is what you study."&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  the honesty stuff, since it matters here
&lt;/h2&gt;

&lt;p&gt;Two lines from the page, quoted because I want to be held to them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Nothing here is gated." The repertoire explorer, the leak report (which openings are costing you rating), the drill trainer, and PGN export are all free and stay free. Forever, no asterisk.&lt;/li&gt;
&lt;li&gt;"These packs don't change the site." Buying a pack doesn't change any ranking or recommendation anywhere. The rule that picks a pack's moves is printed in full on the page so anyone can check it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm allergic to the version of this where the free tool slowly degrades into a demo. That's not this.&lt;/p&gt;

&lt;h2&gt;
  
  
  honest scale check
&lt;/h2&gt;

&lt;p&gt;This is a small tool with a small audience. I don't have a revenue chart to show you, and this isn't a growth story yet. Today's ship is a conversion fix in the most literal sense: the page used to ask for $9 with nothing to look at, and now it shows real data and hands you 47 free lines first. Whether that actually converts better, idk yet, that's what the next few weeks are for. If it does something interesting either direction I'll write it up.&lt;/p&gt;

&lt;p&gt;If you play on Lichess and want to see which openings are quietly bleeding your rating, the free analysis is the place to start. The pack page with the new preview is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://repertoire-builder.com/repertoire-packs.html?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=packs-devto-0825" rel="noopener noreferrer"&gt;repertoire-builder.com/repertoire-packs.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer anything in the comments, especially from anyone else selling a small paid add-on next to a free tool. Figuring out that boundary honestly has been harder than the code.&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>webdev</category>
      <category>chess</category>
      <category>programming</category>
    </item>
    <item>
      <title>adding role-specific guides to my lol site broke how the whole thing linked together</title>
      <dc:creator>Declan</dc:creator>
      <pubDate>Tue, 25 Aug 2026 16:18:15 +0000</pubDate>
      <link>https://dev.to/buildittheywillcome/adding-role-specific-guides-to-my-lol-site-broke-how-the-whole-thing-linked-together-2eba</link>
      <guid>https://dev.to/buildittheywillcome/adding-role-specific-guides-to-my-lol-site-broke-how-the-whole-thing-linked-together-2eba</guid>
      <description>&lt;p&gt;shipping climbing guides for all 5 roles sounds like a content update, but the actual work was restructuring how every page on the site connects to itself.&lt;/p&gt;

&lt;p&gt;I run lol-practice-system.com, a free league of legends practice/strategy site. this update was supposed to be simple, write some new guides, ship them. shipped a teamfighting fundamentals guide (positioning, target priority), a vision and warding deep-dive, and climbing guides for all 5 roles, top, jungle, mid, adc, support, each one built around what that role actually needs to care ab instead of generic "farm better" advice.&lt;/p&gt;

&lt;p&gt;and that last part is where it stopped being a content update.&lt;/p&gt;

&lt;p&gt;the site used to be one general strategy site, so the structure was basically a flat pile of pages. every page was equally relevant to everyone, which meant linking between them didn't matter much, u land somewhere, u read it, done. the moment content became role-specific that assumption died. a jungle player reading the jungle guide should get routed to the warding deep-dive sections that matter for junglers, the teamfight guide, whatever supports their actual path, not just whatever page happened to exist next to it. a flat pile with role-specific pages sitting in it is honestly worse than a flat pile of general pages, because now there ARE right and wrong next pages and the site wasn't picking either.&lt;/p&gt;

&lt;p&gt;so I did a full internal-linking audit across every page on the site. mapped what each page was for, who it was for, and what the sensible next read was from it, then implemented the links accordingly. tedious, unglamorous, and probably the highest-leverage thing in the whole release. it's the difference between "we have a jungle guide" and "a jungle player can actually move through the site like it was built for them." also helps search engines understand the structure, which was a nice side effect rather than the goal.&lt;/p&gt;

&lt;p&gt;while I was in there I added IndexNow support too, so new/updated pages ping bing, yandex, naver, seznam and yep instantly instead of waiting around for normal crawl schedules. small thing, but when u ship a batch of new pages at once it's nice to not just sit there hoping a crawler shows up eventually.&lt;/p&gt;

&lt;p&gt;lesson for me was that "add more content" is never actually the task once the content stops being one-size-fits-all, the structure is the task.&lt;/p&gt;

&lt;p&gt;site's at &lt;a href="https://lol-practice-system.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=role-guides-0825" rel="noopener noreferrer"&gt;https://lol-practice-system.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=role-guides-0825&lt;/a&gt; if u want to see how it actually turned out.&lt;/p&gt;

&lt;p&gt;curious how other people handle this, do u do internal linking by hand like I did, or have u automated it somehow (tag-based, graph-based, whatever)? mine was manual and I can already feel it not scaling.&lt;/p&gt;

</description>
      <category>lol</category>
      <category>strategy</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>I built a local heuristic to catch AI sounding product copy. Here is what it actually catches and what it misses.</title>
      <dc:creator>Declan</dc:creator>
      <pubDate>Sun, 23 Aug 2026 20:18:24 +0000</pubDate>
      <link>https://dev.to/buildittheywillcome/i-built-a-local-heuristic-to-catch-ai-sounding-product-copy-here-is-what-it-actually-catches-and-1n73</link>
      <guid>https://dev.to/buildittheywillcome/i-built-a-local-heuristic-to-catch-ai-sounding-product-copy-here-is-what-it-actually-catches-and-1n73</guid>
      <description>&lt;p&gt;This week I packaged a small analyzer I had been testing as a Chrome extension: Copy Tell. It checks product descriptions and posts on Gumroad and Substack for the kind of stock phrasing an unedited AI writing tool tends to produce, and shows a small notice if enough of it shows up.&lt;/p&gt;

&lt;p&gt;No ML model. Pure lexical and stylometric scoring: stock phrase density, symmetric list framing used as filler, sentence length uniformity, a few other signals. Everything runs in the page's own JavaScript context. Nothing is sent anywhere.&lt;/p&gt;

&lt;p&gt;I tested it against a 100 sample labeled set: 50 AI generated product descriptions, 50 real human written descriptions pulled from published npm package READMEs.&lt;/p&gt;

&lt;p&gt;Results:&lt;br&gt;
tp 39, fp 1, tn 49, fn 11&lt;br&gt;
precision 0.975, recall 0.78, f1 0.867, accuracy 0.88&lt;/p&gt;

&lt;p&gt;Precision is strong. When it calls something likely AI, it is right 97.5% of the time. Recall is the honest weak point: it misses 22% of the AI samples outright. The 11 misses share a pattern, all written in a plainer, more literal register (a garden hose description, an area rug, a smart thermostat) with none of the stock phrasing the analyzer is built to catch. That is a real limitation of a rule based approach, not a bug I can patch away without adding actual language understanding, which is a different, heavier tool than this one.&lt;/p&gt;

&lt;p&gt;One false positive too: axe-core's real README, flagged mainly for a single phrase a human author also happened to use. A fair miss, not cherry picked.&lt;/p&gt;

&lt;p&gt;The test set itself has a gap worth stating plainly: it is AI copy versus real technical documentation, not real marketplace listing copy. Sellers tend to lean on superlatives more than a README does, so real world precision on actual Gumroad or Substack listings is probably lower than the number above. Not yet measured against real seller copy specifically. That validation is the obvious next step.&lt;/p&gt;

&lt;p&gt;Extension is live and free: &lt;a href="https://chromewebstore.google.com/detail/copy-tell-ai-description/ehpkbnkcpbfkagcfmbofldfnpnmopcbi" rel="noopener noreferrer"&gt;https://chromewebstore.google.com/detail/copy-tell-ai-description/ehpkbnkcpbfkagcfmbofldfnpnmopcbi&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you run it against your own listing and it gets a call wrong in either direction, I would like to know.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>buildinpublic</category>
      <category>productivity</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How We Handle Client-Side CSV Merging Without Server Processing</title>
      <dc:creator>Declan</dc:creator>
      <pubDate>Fri, 21 Aug 2026 21:04:37 +0000</pubDate>
      <link>https://dev.to/buildittheywillcome/how-we-handle-client-side-csv-merging-without-server-processing-25l8</link>
      <guid>https://dev.to/buildittheywillcome/how-we-handle-client-side-csv-merging-without-server-processing-25l8</guid>
      <description>&lt;p&gt;When merging CSVs in the browser, handling mismatched columns and quoted cells changes everything. Here's how filetools does it.&lt;/p&gt;

&lt;p&gt;Last week we shipped CSV merge/split/transpose tools for filetools, and the most interesting challenge wasn't CSV parsing - it was handling real-world data without a server. Here's how we handle the hard cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CSV files in the wild are messy. Columns don't always match. A cell value contains a comma and that comma is quoted. Headers are sometimes case-sensitive, sometimes not. When you build on a server, you can run a fast library and stream the result. In the browser, you have to make your merge operation deterministic from first load.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Column matching:&lt;/strong&gt; Users specify which columns to merge on (e.g., "id" or "email"). We do a case-insensitive first pass, then check for exact matches. If no match exists, we warn the user and ask them to pick from the detected headers. This upfront clarity saves merge errors later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quoted cell handling:&lt;/strong&gt; We follow RFC 4180 strictly - a quote inside a quoted field is escaped as a double quote. Most CSV parsers get this wrong when they're quick. We use the &lt;code&gt;csv-parse&lt;/code&gt; library (MIT) vendored into the site, same way we do with PDF and ZIP libraries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Column order:&lt;/strong&gt; The merge operation respects column order from the first file, then appends any new columns from subsequent files. This is deterministic and reproducible.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why this matters for a browser tool:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Server-based CSV tools hide their assumptions - you upload, they merge, you download. If a merge fails, you get an error message and no insight into why. Client-side, the user can see the detected headers, approve or correct them, and re-try immediately. That transparency matters when you're dealing with data that represents real records or transactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What shipped this week:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We added merge, split (by row count or column value), transpose, and comparison tools. The same deterministic, transparent approach applies to each one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next question:&lt;/strong&gt; what's the most painful CSV operation that currently requires downloading a tool or writing a script? We're thinking about row-level filtering and conditional formatting next.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>tools</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building File Utilities That Run 100% in the Browser</title>
      <dc:creator>Declan</dc:creator>
      <pubDate>Thu, 20 Aug 2026 18:42:48 +0000</pubDate>
      <link>https://dev.to/buildittheywillcome/building-file-utilities-that-run-100-in-the-browser-ie4</link>
      <guid>https://dev.to/buildittheywillcome/building-file-utilities-that-run-100-in-the-browser-ie4</guid>
      <description>&lt;p&gt;I recently built filetools, a suite of file utilities that run entirely in the browser. No server backend, no file uploads, no data collection.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Existing tools for CSV extraction, PDF manipulation, and table conversion often require uploading files or creating accounts. That creates friction and privacy concerns. But these tasks are fundamentally simple: extracting text from a PDF or parsing a CSV can happen entirely in JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;filetools is a collection of single-purpose utilities:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PDF Tools:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Merge, split, rotate PDFs&lt;/li&gt;
&lt;li&gt;Extract tables from PDFs to CSV&lt;/li&gt;
&lt;li&gt;Convert bank statements to CSV&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Tools:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extract tables from HTML to CSV or JSON&lt;/li&gt;
&lt;li&gt;Convert between XLSX, JSON, YAML, and CSV&lt;/li&gt;
&lt;li&gt;Remove duplicate lines, sort CSV files, merge/compare data files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each tool is its own page, targeting one specific task without bloat.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why static hosting?&lt;/strong&gt; Keeps infrastructure simple and costs near zero. Files are built once, served from GitHub Pages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why client-side only?&lt;/strong&gt; User files never leave their machine. Processing is fast (no network round-trip). Privacy is the default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tech stack:&lt;/strong&gt; vanilla JavaScript using npm libraries (pdfjs-dist, exceljs, js-yaml, pdf-lib) - no framework, no server. Each page is roughly 5-15KB gzipped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design:&lt;/strong&gt; Started with demand mining, looking at actual Google search queries and autocomplete suggestions to pick which tools to build first.&lt;/p&gt;

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

&lt;p&gt;Live site: &lt;a href="https://usefiletools.com/?utm_source=dev.to&amp;amp;utm_medium=article&amp;amp;utm_campaign=filetools-launch"&gt;https://usefiletools.com/?utm_source=dev.to&amp;amp;utm_medium=article&amp;amp;utm_campaign=filetools-launch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm building more tools based on real search demand. If there's a file utility you've always wished existed, especially for data professionals, I'd love to hear about it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>privacy</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
