<?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: Justinnnnnnn045</title>
    <description>The latest articles on DEV Community by Justinnnnnnn045 (@justinnnnnnn045).</description>
    <link>https://dev.to/justinnnnnnn045</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%2F4108777%2Fff96a8c4-8144-47c6-aae8-6715e0dff65c.png</url>
      <title>DEV Community: Justinnnnnnn045</title>
      <link>https://dev.to/justinnnnnnn045</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/justinnnnnnn045"/>
    <language>en</language>
    <item>
      <title>My leaderboard site updates itself while I sleep — pure-stdlib Python, GitHub Actions, zero servers</title>
      <dc:creator>Justinnnnnnn045</dc:creator>
      <pubDate>Mon, 07 Sep 2026 10:12:43 +0000</pubDate>
      <link>https://dev.to/justinnnnnnn045/my-leaderboard-site-updates-itself-while-i-sleep-pure-stdlib-python-github-actions-zero-servers-omp</link>
      <guid>https://dev.to/justinnnnnnn045/my-leaderboard-site-updates-itself-while-i-sleep-pure-stdlib-python-github-actions-zero-servers-omp</guid>
      <description>&lt;p&gt;My side project, &lt;a href="https://justinnnnnnn045.github.io/pd-engine/" rel="noopener noreferrer"&gt;PD.Radar&lt;/a&gt;, ranks resources mentioned in big Ask HN threads by &lt;strong&gt;citations&lt;/strong&gt; (distinct commenters naming the thing), not by upvotes. Upvotes measure drama; citations measure how many people independently bothered to name the same resource.&lt;/p&gt;

&lt;p&gt;The site went live with one leaderboard: 540 comments from "What is the best money you have spent on professional development?", 24 resources ranked. Therapy won with 51 citations. Not a course, not a book.&lt;/p&gt;

&lt;p&gt;Then came the problem every static site has: &lt;strong&gt;the data was frozen on the day I built it.&lt;/strong&gt; The fix wasn't updating it by hand every morning — that's a hobby for people with more patience than me. The fix was making the site mine its own new content.&lt;/p&gt;

&lt;h2&gt;
  
  
  The engine: two jobs, one file, zero dependencies
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;auto_update.py&lt;/code&gt; is ~300 lines of pure stdlib Python. It runs daily on GitHub Actions and does exactly two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Re-mine the flagship thread&lt;/strong&gt; so its numbers stay fresh (and only rewrites the JSON if something actually changed)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discover new Ask HN question threads&lt;/strong&gt;, mine them with the same method, and publish the ones that qualify as new leaderboards&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The site reads a single &lt;code&gt;data/threads.json&lt;/code&gt; index. New file in, new tab on the site. No manual commits, no code changes, no server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MIN_POINTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="n"&gt;MIN_COMMENTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="n"&gt;MIN_RESOURCES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;      &lt;span class="c1"&gt;# a new thread needs &amp;gt;=5 resources matched
&lt;/span&gt;&lt;span class="n"&gt;MIN_CITES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;          &lt;span class="c1"&gt;# ...each with &amp;gt;=3 citations, to publish
&lt;/span&gt;&lt;span class="n"&gt;MAX_NEW_PER_RUN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;    &lt;span class="c1"&gt;# gentle on the Algolia API; quality over volume
&lt;/span&gt;&lt;span class="n"&gt;SKIP_DAYS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;         &lt;span class="c1"&gt;# days to remember a rejected thread before re-checking
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The hard part was the honesty gate, not the mining
&lt;/h2&gt;

&lt;p&gt;Mining is easy — HN has the excellent Algolia API, and fetching every comment of a thread is a loop. The hard part: &lt;strong&gt;how does a script decide a thread is worth publishing without me looking at it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My first fear was false positives. A rant like "Is all of FAANG like this?" has hundreds of comments mentioning Python, Go, books, courses — the lexicon would happily produce a garbage leaderboard out of pure noise. Publishing that would poison the whole premise, because the site's entire promise is &lt;em&gt;verifiable&lt;/em&gt; rankings.&lt;/p&gt;

&lt;p&gt;So the gate is two lists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;INTENT_KEYWORDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;best&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;book&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;books&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;recommend&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;course&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;learn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resource&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resources&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;worth&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;advice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skill&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;skills&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;career&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;study&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;RANT_PATTERNS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;like this&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;just me&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wtf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nuke&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stopped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;banned&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shut down&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;died&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;layoff&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;title_has_intent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;RANT_PATTERNS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;INTENT_KEYWORDS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A thread is only mined if its title asks for recommendations, and a discovered thread only gets &lt;strong&gt;published&lt;/strong&gt; if the lexicon genuinely matches it: at least 5 distinct resources, each with at least 3 separate citations. Weak matches never see the light of day. And everything that gets rejected is remembered for 45 days, so the same thread doesn't get re-evaluated every morning.&lt;/p&gt;

&lt;p&gt;It also runs the same citation matcher that powers the flagship (&lt;code&gt;extract_rank.py&lt;/code&gt;), on purpose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Only import the lexicon + matchers from the existing pipeline so the
# ranking method stays IDENTICAL across threads.
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;extract_rank&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LEXICON&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flatten_comments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;load_flat&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One method, every thread. If I ever improve the matcher, every leaderboard improves with it — and stays comparable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually happened on the first runs
&lt;/h2&gt;

&lt;p&gt;Discovery queries like "best books", "worth paying for", "best investment in your career" pull candidate threads from Algolia search. Each pass examined dozens of candidates. The first real run:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thread&lt;/th&gt;
&lt;th&gt;Points&lt;/th&gt;
&lt;th&gt;Comments&lt;/th&gt;
&lt;th&gt;Resources ranked&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Best money spent on professional development &lt;em&gt;(flagship)&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;524&lt;/td&gt;
&lt;td&gt;540&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best book / resources on leadership for tech teams?&lt;/td&gt;
&lt;td&gt;882&lt;/td&gt;
&lt;td&gt;209&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best books you read in the past decade?&lt;/td&gt;
&lt;td&gt;873&lt;/td&gt;
&lt;td&gt;417&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Advice for finding an entry-level remote job?&lt;/td&gt;
&lt;td&gt;740&lt;/td&gt;
&lt;td&gt;199&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best computer science book you've read recently?&lt;/td&gt;
&lt;td&gt;670&lt;/td&gt;
&lt;td&gt;186&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;1,551 comments, 66 ranked resources — none of it hand-mined. The flagship is pinned as the site's default tab; the rest sort by points.&lt;/p&gt;

&lt;p&gt;And the rejections are as satisfying as the additions. The run that found the leadership thread also looked at a FAANG rant, a Stripe outage story, and a YC blog post — and correctly declined all three. Watching a script make a defensible editorial call with nobody watching is genuinely the most fun I've had with a side project this year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why GitHub Actions and not a server
&lt;/h2&gt;

&lt;p&gt;Because the whole thing is a static site, the engine's output is just &lt;em&gt;files&lt;/em&gt;. So the deploy pipeline is embarrassingly simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cron fires at 06:17 UTC on a free GitHub Actions runner&lt;/li&gt;
&lt;li&gt;The script fetches from Algolia, mines, decides&lt;/li&gt;
&lt;li&gt;If anything changed: commit + push (as a bot user)&lt;/li&gt;
&lt;li&gt;GitHub Pages redeploys automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Total monthly cost: &lt;strong&gt;$0&lt;/strong&gt;. Total infrastructure: a YAML file that's 20 lines long. The commit history doubles as a changelog of every autonomous editorial decision the engine has made.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The lexicon is hand-built.&lt;/strong&gt; It knows ~90 resources across books, courses, tools. A great comment recommending something it doesn't know is invisible to the ranking. Growing the lexicon is ongoing, boring, necessary work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discovery depends on Algolia search.&lt;/strong&gt; If a qualifying thread never surfaces in my queries, it never gets mined. The 7 discovery queries cast a decent net, but it's a net, not a census.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Citations ≠ quality.&lt;/strong&gt; The ranking proves what a community &lt;em&gt;mentioned&lt;/em&gt;, not what changed anyone's life. The #1 professional-development answer being "therapy" (51 citations) is probably the most honest thing on the whole site precisely because no marketing budget could have produced it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The site: &lt;a href="https://justinnnnnnn045.github.io/pd-engine/" rel="noopener noreferrer"&gt;PD.Radar — ranked answers from real threads&lt;/a&gt; — five leaderboards live, each with the receipts (every resource links back to actual comments in its source thread).&lt;/p&gt;

&lt;p&gt;The engine: &lt;a href="https://github.com/Justinnnnnnn045/pd-engine" rel="noopener noreferrer"&gt;auto_update.py in the repo&lt;/a&gt; — steal the honesty-gate pattern if you're building anything that publishes without supervision. The gate is the product.&lt;/p&gt;

&lt;p&gt;If you've got an Ask HN thread you'd love to see ranked this way, drop the link in the comments — the engine takes requests now.&lt;/p&gt;

</description>
      <category>python</category>
      <category>githubactions</category>
      <category>showdev</category>
      <category>data</category>
    </item>
    <item>
      <title>The note-taking stack is broken: Anki still can't talk to your notes (and why that's a product gap)</title>
      <dc:creator>Justinnnnnnn045</dc:creator>
      <pubDate>Sat, 05 Sep 2026 10:04:04 +0000</pubDate>
      <link>https://dev.to/justinnnnnnn045/the-note-taking-stack-is-broken-anki-still-cant-talk-to-your-notes-and-why-thats-a-product-gap-2cl7</link>
      <guid>https://dev.to/justinnnnnnn045/the-note-taking-stack-is-broken-anki-still-cant-talk-to-your-notes-and-why-thats-a-product-gap-2cl7</guid>
      <description>&lt;p&gt;This week a Hacker News thread made the rounds again: &lt;em&gt;"Ask HN: What tools do you use to take learning notes and organise them?"&lt;/em&gt; (28 points, 26 comments).&lt;/p&gt;

&lt;p&gt;The thread itself is not huge. But the pain in it is old, specific, and still unsolved — and that mismatch is exactly where a product gap hides.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual complaint
&lt;/h2&gt;

&lt;p&gt;The OP is a self-directed learner. They use Anki for spaced repetition and something else (OneNote, Evernote, Obsidian, plain markdown) for long-form notes. And they are stuck in the glue between the two:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Anki is useful but its interface is stuck in the 90s and it doesn't easily sync with my other, more expansive notes."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's not a feature request. It's a description of a workflow that has one job — remember what you learn — and it fails at the seam between its two halves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is a real gap and not just nostalgia
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The two tools got better separately, never together.&lt;/strong&gt; Obsidian grew graph views and a plugin ecosystem. Anki grew better scheduling. Nobody made the bridge feel native.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The people who want this are skilled, motivated, and organised enough to pay.&lt;/strong&gt; Self-directed learners are the exact demographic that buys Pro tools, subscriptions, and plugins for their workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The existing bridges are brittle.&lt;/strong&gt; Most are scripts, CSV exports, or add-ons that break on updates. The pain persists because the solution is treated as a weekend script, not a product.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What a product would actually look like
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;markdown vault + spaced repetition in one place&lt;/strong&gt; — not two windows and a sync script, but one surface where &lt;code&gt;#flashcard&lt;/code&gt; blocks are just part of the note.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sync that doesn't rot.&lt;/strong&gt; The workflow survives app updates because the storage format is plain files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero-config setup&lt;/strong&gt; for the 90% case. Import a folder, get a deck. No CSV, no add-on fiddling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this matters for builders
&lt;/h2&gt;

&lt;p&gt;This thread is a small-but-perfect example of how to read a market: &lt;strong&gt;a repeated, specific complaint with a committed audience and a brittle existing answer.&lt;/strong&gt; Not every opportunity is 500 points on HN. Some are 26 comments long and still the right thing to build.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This week's findings come from the daily opportunity brief generated from live Hacker News and Stack Exchange signals.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What's your note stack? Is Anki the missing link or the wrong tool? Tell me in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>productivity</category>
      <category>tools</category>
      <category>career</category>
    </item>
    <item>
      <title>The #1 professional-development spend of 540 engineers isn't a book</title>
      <dc:creator>Justinnnnnnn045</dc:creator>
      <pubDate>Thu, 03 Sep 2026 23:03:34 +0000</pubDate>
      <link>https://dev.to/justinnnnnnn045/the-1-professional-development-spend-of-540-engineers-isnt-a-book-4kgm</link>
      <guid>https://dev.to/justinnnnnnn045/the-1-professional-development-spend-of-540-engineers-isnt-a-book-4kgm</guid>
      <description>&lt;p&gt;I spent a weekend reading all 540 comments from Hacker News' biggest Ask HN on professional development: &lt;em&gt;"What is the best money you have spent on professional development?"&lt;/em&gt; (524 points, 540 comments).&lt;/p&gt;

&lt;p&gt;The results surprised me — and they might change where you put your next learning budget.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update (Sep 7):&lt;/strong&gt; this leaderboard no longer covers one thread. The engine now mines qualifying Ask HN threads on its own and publishes them daily — the site is up to &lt;strong&gt;5 leaderboards, 66 resources, 1,551 comments, zero hand-mining&lt;/strong&gt;. Details on how that works (and why it refuses to publish junk) in &lt;a href="https://dev.to/justinnnnnnn045/my-leaderboard-site-updates-itself-while-i-sleep-pure-stdlib-python-github-actions-zero-servers-3gcd"&gt;the follow-up article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The ranking (by how many DISTINCT commenters named it)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Mentions&lt;/th&gt;
&lt;th&gt;Est. price&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Therapy / coaching&lt;/td&gt;
&lt;td&gt;51&lt;/td&gt;
&lt;td&gt;~$100/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Writing / blogging practice&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Refactoring (Martin Fowler)&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;~$45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Designing Data-Intensive Applications&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;~$45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Domain-Driven Design (Eric Evans)&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;~$55&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Toastmasters&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;~$10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Coursera Specializations&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;~$50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;LeetCode&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;~$35&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;MasterClass&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;~$15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;The Pragmatic Programmer&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;~$45&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  The finding that surprised everyone
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Therapy is #1.&lt;/strong&gt; Not a book, not a course, not a certification — the highest-ROI professional-development spend according to 51 distinct engineers was coaching/therapy. The comments overwhelmingly said it unlocked career growth more than any technical book:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"As a founder / CTO the best money I have spent is on a really good coach." — gtf21&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The technical books are still there (Refactoring, DDIA, DDD), but the pattern is clear: once the fundamentals are covered, the biggest gains come from non-technical skills — communication, leadership, and mental health.&lt;/p&gt;

&lt;p&gt;The other four leaderboards back the same pattern from different angles — the leadership-resources thread (882 points) and the decade-of-books thread (873 points) both rank, among real practitioners, communication and judgment books above tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methodology (what makes this honest)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A 524-point Ask HN thread asked the question and got 540 answers.&lt;/li&gt;
&lt;li&gt;I read &lt;strong&gt;all 540 comments&lt;/strong&gt; and ranked every resource by how many &lt;strong&gt;distinct people&lt;/strong&gt; named it.&lt;/li&gt;
&lt;li&gt;Not ranked by marketing. Not ranked by affiliate commission. Ranked by what engineers actually paid for and recommended.&lt;/li&gt;
&lt;li&gt;Prices are &lt;strong&gt;labeled as estimates&lt;/strong&gt;. No fake numbers, ever.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The interactive version
&lt;/h2&gt;

&lt;p&gt;66 resources across 5 threads, grouped by price tier, searchable, with real quotes behind every item — every ranking verifiable against its source thread in seconds:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://justinnnnnnn045.github.io/pd-engine/" rel="noopener noreferrer"&gt;https://justinnnnnnn045.github.io/pd-engine/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Related: &lt;a href="https://dev.to/justinnnnnnn045/the-note-taking-stack-is-broken-anki-still-cant-talk-to-your-notes-and-why-thats-a-product-gap-2cl7"&gt;the Anki/Obsidian gap I found while building this&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What did YOU spend PD money on that's missing from the list?&lt;/em&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>learning</category>
      <category>books</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
