<?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: Karlis</title>
    <description>The latest articles on DEV Community by Karlis (@acaciaman).</description>
    <link>https://dev.to/acaciaman</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%2F3791733%2F70065550-3638-41d8-b409-07d25312f4e8.png</url>
      <title>DEV Community: Karlis</title>
      <link>https://dev.to/acaciaman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/acaciaman"/>
    <language>en</language>
    <item>
      <title>Can We Quantify Political Clarity? An AI Experiment</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Mon, 07 Sep 2026 11:33:54 +0000</pubDate>
      <link>https://dev.to/acaciaman/can-we-quantify-political-clarity-an-ai-experiment-4gk0</link>
      <guid>https://dev.to/acaciaman/can-we-quantify-political-clarity-an-ai-experiment-4gk0</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Every election cycle, politicians make hundreds of promises. Some are specific: "Increase pensions by 50 euros by Q2 2027." Others are vague: "Strengthen our healthcare system." Most voters never know which candidates are actually committing to measurable goals versus just saying what sounds good.&lt;/p&gt;

&lt;p&gt;This matters because specificity correlates with implementation capability. A candidate who names exact figures, timelines, and legislation can be held accountable. A candidate who speaks only in aspirations often cannot.&lt;/p&gt;

&lt;p&gt;The question: Can we systematically measure this gap?&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing the Program Specificity Index
&lt;/h2&gt;

&lt;p&gt;We built a framework that categorizes every policy claim into three tiers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Concrete Plans (🟢):&lt;/strong&gt; Specific numerical targets, exact timelines, named legislative acts, or measurable milestones. Example: "Cut corporate tax rate to 15% by 2027."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;General Direction (🟡):&lt;/strong&gt; Policy intent without implementation detail. Commitment exists but lacks numbers, timelines, or methods. Example: "Support small business growth."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Empty Slogans (🔴):&lt;/strong&gt; Uncosted aspirations or emotional appeals too vague to be actionable. Example: "Build a brighter future."&lt;/p&gt;

&lt;p&gt;Every claim in a political program gets assigned to one tier. The result: a "specificity score" (percentage of concrete claims) for each candidate or party.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Data Showed
&lt;/h2&gt;

&lt;p&gt;We analyzed over 1,000 policy claims across a full slate of political programs and found:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Specificity varies wildly:&lt;/strong&gt; Top performers scored 56% concrete claims; bottom performers scored 7%. This gap is meaningful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Some sectors are always vague:&lt;/strong&gt; Healthcare and education promises were systematically less specific than tax or defense promises, regardless of who made them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Family benefits dominate concrete language:&lt;/strong&gt; Pension and child-benefit pledges consistently included exact euro amounts. When politicians want to show specificity, this is where they do it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Party age matters:&lt;/strong&gt; Newer, single-leader parties averaged much higher specificity scores than long-established coalition parties, which relied heavily on abstract phrasing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Universal boilerplate exists:&lt;/strong&gt; Across all parties, identical defense spending commitments ("5% of GDP") appeared verbatim. Same language, different lips.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How We Built This: The Technology Stack
&lt;/h2&gt;

&lt;p&gt;The analysis pipeline relied on three layers of AI:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Text parsing and claim extraction:&lt;/strong&gt; We fed entire political programs to Claude Sonnet (Anthropic's mid-tier model, optimized for reasoning) to parse natural language and extract distinct policy statements. The model filtered out meta-commentary, introductions, and repeated phrasing to identify unique claims worth categorizing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Multi-tier classification:&lt;/strong&gt; Each claim was classified by Sonnet using the three-tier framework. The model applied consistent logic: Does this claim contain at least one concrete element (a number, date, percentage, or specific action)? If yes: 🟢. If it names intent but lacks implementation detail: 🟡. If it is pure aspiration: 🔴.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Sector tagging and aggregation:&lt;/strong&gt; Every claim was also tagged by policy domain (Economy, Healthcare, Education, Defense, Social Protection, etc.). This allowed us to measure specificity not just by party, but by sector within each party. We aggregated counts, percentages, and patterns across all 1,000+ claims to generate summary statistics.&lt;/p&gt;

&lt;p&gt;The entire workflow ran in a single pipeline: parse → categorize → tag → aggregate → summarize. Sonnet's reasoning capability was essential because political language is slippery. The model had to distinguish between "we will raise pensions" (general direction) and "we will raise pensions by 50 euros" (concrete plan). That nuance requires understanding, not just keyword matching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;This framework demonstrates that AI can be applied to civic accountability. Instead of relying on journalist instinct or voter intuition, we used systematic analysis to measure a concrete property of political communication: specificity.&lt;/p&gt;

&lt;p&gt;The method is replicable. Any country running an election can apply this same framework to their own candidates or parties. The three-tier system is universal. The AI pipeline is straightforward. The results are transparent (every claim can be reviewed).&lt;/p&gt;

&lt;p&gt;More broadly, this shows how LLMs can be used for data journalism and civic tech. The model does not make judgments about right or wrong policy. It measures an objective property: Is this claim specific enough to implement and verify?&lt;/p&gt;

&lt;h2&gt;
  
  
  Apply This to Your Elections
&lt;/h2&gt;

&lt;p&gt;If you are running an election in your country, you can replicate this analysis. The framework needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full text of candidate or party programs (in any language Claude understands).&lt;/li&gt;
&lt;li&gt;Clear definitions of what "concrete," "general," and "vague" mean in your political context (adapt the examples).&lt;/li&gt;
&lt;li&gt;A few minutes of AI API time to run the classification.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output: A ranked list of candidates or parties by specificity score, plus sector-level breakdowns showing which policy areas get concrete treatment and which are left vague.&lt;/p&gt;

&lt;p&gt;This is useful for voters. It is also useful for researchers studying how political communication changes over time or across regions.&lt;/p&gt;

&lt;p&gt;What would you measure if you built this for your own elections?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>civictech</category>
      <category>datascience</category>
    </item>
    <item>
      <title>Fixing Boring Playoff Brackets: Why Injecting 1–2 Random Games Skyrockets Tournament Hype</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Mon, 31 Aug 2026 01:30:14 +0000</pubDate>
      <link>https://dev.to/acaciaman/fixing-boring-playoff-brackets-why-injecting-1-2-random-games-skyrockets-tournament-hype-2lnl</link>
      <guid>https://dev.to/acaciaman/fixing-boring-playoff-brackets-why-injecting-1-2-random-games-skyrockets-tournament-hype-2lnl</guid>
      <description>&lt;p&gt;Every developer building a tournament engine or game format hits the exact same wall: &lt;strong&gt;Standard static brackets are predictable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a traditional 8-team single-elimination bracket, Seed #1 plays Seed #8, Seed #2 plays Seed #7, and so on. Mathematically, it's fair. From a broadcast and engagement perspective, it’s a snoozefest. Early rounds are plagued by predictable blowouts, and 90% of the tournament's hype is backloaded into the Semifinals and Finals.&lt;/p&gt;

&lt;p&gt;To fix this, many system designers suggest blowing up the bracket entirely—switching to full double-elimination, multi-tier group pots, or complex ladder systems. But you don't need to rebuild the wheel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The most effective solution is micro-targeted: Inject just 1 or 2 randomly assigned games into the early playoff rounds while keeping the rest of the system rank-seeded.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Concept: "Controlled Volatility"
&lt;/h2&gt;

&lt;p&gt;You do &lt;strong&gt;not&lt;/strong&gt; need to randomize the entire tournament, nor do you need to convert your league into a complex pot-based group stage.&lt;/p&gt;

&lt;p&gt;Instead, you keep standard regular-season rankings as the baseline, but inject &lt;strong&gt;1 to 3 randomized wildcard games&lt;/strong&gt; in the opening phase of the postseason.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works in an 8-Team Playoff
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;The Rank Protection (1 Game):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  * **Seed \#1 vs Seed \#8** remains statically locked.
  * *Why?* Top seeds earned their advantage during the regular season, and bottom seeds shouldn't get a free pass.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;The Controlled Randomness (2 Games):&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  * Instead of automatically pairing \#2 vs \#7, \#3 vs \#6, and \#4 vs \#5, place **Seeds \#2, \#3, \#4, \#5, \#6, and \#7** into a live, randomized lottery pool.
  * Draw 3 matches randomly from this pool.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;               [ 8 PLAYOFF TEAMS ]  
              /                   \  
 [ Top &amp;amp; Bottom Seeds ]       [ Mid-Table Seeds ]  
      (#1 &amp;amp; #8)             (#2, #3, #4, #5, #6, #7)  
          │                            │  
          ▼                            ▼  
 FIXED RANK MATCHES            RANDOMIZED LOTTERY  
  • Match 1: #1 vs #8           • Match 2: Random Draw A  
                                • Match 3: Random Draw B  
                                • Match 4: Random Draw C 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By randomizing just 1 or 2 early matches, you instantly transform predictable mid-table fixtures into explosive, high-stakes coin-flips without burning top-seed regular season value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Algorithmic Implementation (Python Engine)
&lt;/h2&gt;

&lt;p&gt;If you are writing a tournament routing engine, combining deterministic seeding with a randomized early-round pool is straightforward:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;  

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Team&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;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;  
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;seed&lt;/span&gt;  

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ControlledVolatilityBracket&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;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;teams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Team&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;  
        &lt;span class="c1"&gt;# Requires 8 teams ordered by seed 1 to 8  
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;teams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;teams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seed&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;generate_round_1_matchups&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;  
        &lt;span class="n"&gt;matchups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;  

        &lt;span class="c1"&gt;# 1. Deterministic Lock for Seed 1 vs Seed 8  
&lt;/span&gt;        &lt;span class="n"&gt;matchups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&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;Seeded&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;home&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;teams&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;teams&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt;  

        &lt;span class="c1"&gt;# 2. Random Lottery Pool for Seeds 2-7  
&lt;/span&gt;        &lt;span class="n"&gt;random_pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;teams&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  
        &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shuffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random_pool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  

        &lt;span class="c1"&gt;# Draw 3 randomized matches  
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
            &lt;span class="n"&gt;matchups&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&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;Random&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;home&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;random_pool&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;away&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;random_pool&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt;  

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;matchups&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Case Studies: Does Randomness Actually Work?
&lt;/h2&gt;

&lt;p&gt;We don't have to guess whether early-stage randomness increases viewership—major sports and esports leagues have already proven it:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. League of Legends Worlds (The Swiss Stage Shift)
&lt;/h3&gt;

&lt;p&gt;In 2023, Riot Games ditched static groups in favor of a &lt;strong&gt;Swiss Stage&lt;/strong&gt;, where teams with identical win-loss records are drawn randomly live on stream in early rounds.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Result:&lt;/strong&gt; Viewership during the opening randomized days broke historical broadcast records. Viewers tuned in en masse because marquee top-tier teams could randomly collide on Day 1 rather than waiting for the Semifinals.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. UEFA Champions League (The Hybrid 8-Game Phase)
&lt;/h3&gt;

&lt;p&gt;Starting in 2024, European football replaced static 4-team groups with a single 36-team league phase where each team plays 8 games. While teams are seeded into pots, software randomly selects their specific 8 opponents.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Result:&lt;/strong&gt; Broadcasters reported massive year-on-year increases in viewership hours during early rounds. Randomly forcing heavyweight clubs to meet early eliminated the traditional "dead phase" of early-season group play.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. English FA Cup (The Open Random Draw)
&lt;/h3&gt;

&lt;p&gt;The world's oldest soccer tournament uses an unseeded, completely open random draw for every single round.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Result:&lt;/strong&gt; It creates two of the most popular broadcast tropes in sports: &lt;strong&gt;The Giant-Killing&lt;/strong&gt; (an amateur club randomly drawing a giant at home) and &lt;strong&gt;The Early Blockbuster&lt;/strong&gt; (two title favorites colliding in Round 1).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why 1–2 Random Games Solve the Hype Dilemma
&lt;/h2&gt;

&lt;p&gt;From a system architecture and behavioral psychology standpoint, injecting minor randomness delivers three key wins:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Eliminates the "Dead Phase":&lt;/strong&gt; Standard brackets treat Round 1 as procedural filler. Randomizing 1 or 2 matches brings marquee intensity to Day 1.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Generates Free Broadcast Content:&lt;/strong&gt; The "Draw Event" (spinning a wheel or drawing balls live on TV) becomes a standalone broadcast spectacle that drives social media engagement before a single game is played.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Preserves Competitive Integrity:&lt;/strong&gt; Because top seed #1 maintain the earned matchup against lower seed, the regular season still matters. You get the hype of randomness without the unfairness of a pure lottery.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;You don't need a convoluted bracket shape to make playoffs interesting. By blending &lt;strong&gt;75% rank-based stability with 25% controlled randomness&lt;/strong&gt;, you eliminate predictable filler, increase early-round screen time, and create a system that caters to both competitive purists and casual fans.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How do you handle tournament seeding in your projects? Would you introduce random lottery matches into traditional brackets, or do you prefer pure deterministic trees? Let's discuss in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>algorithms</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>AI generated test cases to improve application stability</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Fri, 07 Aug 2026 11:06:12 +0000</pubDate>
      <link>https://dev.to/acaciaman/ai-generated-test-cases-to-improve-application-stability-4g2i</link>
      <guid>https://dev.to/acaciaman/ai-generated-test-cases-to-improve-application-stability-4g2i</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Smash Stories&lt;/a&gt; powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  AI suggestion
&lt;/h1&gt;

&lt;p&gt;Now my side projects I develop using AI. Usual prompt for me is to ask how to improve the project. Usually one of the suggestions is to add more tests. I am a developer and not a tester, therefore to do the good necessary test coverage part I leave to AI. As for me, application testing is not trivial and I accept that each one can develop his/her own testing strategy and it is totally fine.    &lt;/p&gt;

&lt;h1&gt;
  
  
  Acacia-Log example and gained experience
&lt;/h1&gt;

&lt;p&gt;For example, &lt;a href="https://github.com/AcaciaMan/acacia-log" rel="noopener noreferrer"&gt;Acacia-log&lt;/a&gt; project. First time AI generated a lot of tests &lt;a href="https://github.com/AcaciaMan/acacia-log/commit/49d3c8ca44cb393eb606eb1674b8eda3829620d7" rel="noopener noreferrer"&gt;Added testing and improved performance&lt;/a&gt;. The generated tests did not find any bugs (AI has hard job at finding bugs in it's own code), but further development improved by far. After each feature addition, AI is able to do improved testing and early catch changes that broke previous logic.&lt;/p&gt;

&lt;p&gt;Screenshot of AI adding new features (last step is doing verification):&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6abmhzvcqdbpme58wovd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6abmhzvcqdbpme58wovd.png" alt="feature verification" width="799" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example of the prompt for Phase 5 generation:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvvk386uvgs3web70jmol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvvk386uvgs3web70jmol.png" alt="code generation in phases" width="799" height="466"&gt;&lt;/a&gt; &lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
    </item>
    <item>
      <title>Practicing “Database Insights”: where to find real schemas?</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Tue, 05 May 2026 11:55:25 +0000</pubDate>
      <link>https://dev.to/acaciaman/practicing-database-insights-where-to-find-real-schemas-58l4</link>
      <guid>https://dev.to/acaciaman/practicing-database-insights-where-to-find-real-schemas-58l4</guid>
      <description>&lt;p&gt;We talk a lot about “data-driven decisions”, but that usually hides three separate layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data itself (events, transactions, logs, etc.). &lt;/li&gt;
&lt;li&gt;Database structure (schemas, constraints, relationships). &lt;/li&gt;
&lt;li&gt;Insights on top (from SQL, AI copilots, BI tools, notebooks). &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My current interest is in that middle layer: using real-world database structures as a playground to practice &lt;strong&gt;database insights&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding and improving data quality (missing constraints, odd cardinalities, misuse of types). &lt;/li&gt;
&lt;li&gt;Suggesting schema improvements for future analytics (indexes, normalization vs denormalization, slowly changing dimensions, etc.). &lt;/li&gt;
&lt;li&gt;Making access easier via views, semantic layers, or documentation (ERDs, db docs, column descriptions). &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m looking for good open source repositories that contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Non-trivial database schemas (preferably SQL migrations or DBML, not just ORM models).&lt;/li&gt;
&lt;li&gt;Some realistic sample data if possible (to check cardinalities, null patterns, etc.). &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  I’m collecting good open-source schemas to practice database insights; here’s what I’m looking for and I’d love your suggestions.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Do you know &lt;strong&gt;specific GitHub repos&lt;/strong&gt; with interesting database schemas (preferably with migrations + demo data) that are good for practicing:

&lt;ul&gt;
&lt;li&gt;data quality checks,
&lt;/li&gt;
&lt;li&gt;schema critique,
&lt;/li&gt;
&lt;li&gt;documentation and visualization?
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Have you tried using AI tools on top of real schemas to propose constraints, rename columns, or design better access patterns? How did that go? &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Drop any links or examples you have – especially repos where the schema itself is a central part of the project.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>database</category>
      <category>data</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Acacia DB for VS Code: Map your database usage in source code (1.0.0 1.2.0)</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Thu, 30 Apr 2026 12:25:11 +0000</pubDate>
      <link>https://dev.to/acaciaman/acacia-db-for-vs-code-map-your-database-usage-in-source-code-100-120-93a</link>
      <guid>https://dev.to/acaciaman/acacia-db-for-vs-code-map-your-database-usage-in-source-code-100-120-93a</guid>
      <description>&lt;p&gt;If you've ever inherited a legacy system and asked &lt;em&gt;"which tables are actually used, where, and how do they connect?"&lt;/em&gt; — that's the question &lt;a href="https://marketplace.visualstudio.com/items?itemName=manacacia.acacia-db" rel="noopener noreferrer"&gt;Acacia DB&lt;/a&gt; tries to answer.&lt;/p&gt;

&lt;p&gt;It's a VS Code extension that scans your workspace for references to database tables and columns, then turns the raw matches into something you can navigate, rank, and diagram. No LLMs, no cloud calls — just a deterministic pipeline over your source tree and a &lt;code&gt;tables_views.json&lt;/code&gt; schema file.&lt;/p&gt;

&lt;p&gt;The last three releases (1.0.0, 1.1.0, 1.2.0) reshaped the extension from a workspace scanner into a small analysis suite. Here's what landed.&lt;/p&gt;




&lt;h2&gt;
  
  
  1.0.0 — The pipeline rewrite
&lt;/h2&gt;

&lt;p&gt;1.0.0 is the first stable release. The headline change is that the column-relationship analysis pipeline was rewritten end-to-end for both performance and correctness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parallel column-link analysis.&lt;/strong&gt; Column matching now runs in a &lt;code&gt;worker_threads&lt;/code&gt; pool (&lt;code&gt;min(cpus, 8)&lt;/code&gt; workers), with an in-process async fallback when the worker bundle isn't available. File I/O and matching overlap across cores instead of stalling on a single thread.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Targeted line scanning.&lt;/strong&gt; Workers no longer read every line of every file. They open only the line numbers already recorded in &lt;code&gt;table_refs.json&lt;/code&gt; for each file, so the second pass costs a fraction of the first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One global matcher instead of many.&lt;/strong&gt; Previously a fresh column matcher was rebuilt per table and per file. Now a single matcher is built once at the start of analysis and shared across all workers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trie-level fast paths.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An ASCII first-character bitset gives O(1) reject for non-candidate characters before any trie walk.&lt;/li&gt;
&lt;li&gt;The matcher operates on &lt;code&gt;charCodeAt&lt;/code&gt; directly instead of &lt;code&gt;text.split('')&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The quote-skip state machine is bypassed on lines with no &lt;code&gt;"&lt;/code&gt; or &lt;code&gt;'&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;On rejection, the matcher skips the rest of the current word in one pass.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pre-filter for impossible files.&lt;/strong&gt; Files whose in-scope tables can't contribute at least two candidate columns are skipped before any I/O.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O(1) link recording.&lt;/strong&gt; Each &lt;code&gt;LinkedTableInfo&lt;/code&gt; now carries a &lt;code&gt;Map&amp;lt;key, ColumnLink&amp;gt;&lt;/code&gt; plus per-link/per-info &lt;code&gt;Set&amp;lt;string&amp;gt;&lt;/code&gt; file caches, so &lt;code&gt;recordColumnLink&lt;/code&gt; is O(1) per call instead of O(k) over the link array and O(n) over the file array.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Correctness fix: case-sensitive matching with shared lowercased prefix.&lt;/strong&gt; Adding two column names that lowercased to the same string (e.g. &lt;code&gt;"ABC"&lt;/code&gt; and &lt;code&gt;"abc"&lt;/code&gt;) used to clobber each other on the shared trie path — case-sensitive lookup could return the wrong canonical name or no match at all. Each terminal node now stores all case variants, and case-sensitive lookup resolves to the variant that actually appears in the text.&lt;/p&gt;

&lt;p&gt;The dead pairwise per-file analyzer and the legacy &lt;code&gt;processLines&lt;/code&gt; / &lt;code&gt;processFileStream&lt;/code&gt; / &lt;code&gt;processLine&lt;/code&gt; helpers were removed; the orchestrator now drives a single unified pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  1.1.0 — Hot-Path analysis and a leaner JSON format
&lt;/h2&gt;

&lt;p&gt;1.1.0 added an insight layer on top of the raw usage index, and reshaped the persisted analysis file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hot-Path Analysis
&lt;/h3&gt;

&lt;p&gt;A new module, &lt;code&gt;src/hotPathAnalyzer.ts&lt;/code&gt;, exposes pure functions: &lt;code&gt;computeTableMetrics&lt;/code&gt;, &lt;code&gt;computeEdgeMetrics&lt;/code&gt;, &lt;code&gt;suggestIndexes&lt;/code&gt;, &lt;code&gt;suggestCaches&lt;/code&gt;, and &lt;code&gt;buildHotPathReport&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-table metrics:&lt;/strong&gt; &lt;code&gt;usageCount&lt;/code&gt;, &lt;code&gt;fileFanOut&lt;/code&gt;, &lt;code&gt;joinDegreeIn/Out&lt;/code&gt;, weighted PageRank &lt;code&gt;centrality&lt;/code&gt;, and a tunable &lt;code&gt;hotScore&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;$$\text{hotScore} = \log(1 + \text{usageCount}) \cdot (1 + \text{joinDegree}) \cdot \sqrt{\text{fileFanOut}}$$&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Per-edge metrics:&lt;/strong&gt; &lt;code&gt;coOccurrenceCount&lt;/code&gt;, &lt;code&gt;linkConfidence&lt;/code&gt;, and &lt;code&gt;edgeScore = coOccurrenceCount * linkConfidence&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Suggestions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Index suggestions&lt;/strong&gt; for join keys on top-quantile edges, emitted as ready-to-paste DDL: &lt;code&gt;CREATE INDEX IX_&amp;lt;table&amp;gt;_&amp;lt;col&amp;gt; ON &amp;lt;table&amp;gt;(&amp;lt;col&amp;gt;)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache suggestions&lt;/strong&gt; for read-heavy leaf tables (high usage, low join degree).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cold-table&lt;/strong&gt; report (&lt;code&gt;usageCount === 0&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A &lt;strong&gt;Hot Paths tree view&lt;/strong&gt; in the sidebar surfaces five sections: Top Hot Tables, Top Join Paths, Index Suggestions, Cache Candidates, and Cold / Unused Tables. Hot-table and edge leaves reveal the related table in the Database Explorer; index suggestions support a &lt;code&gt;Copy DDL&lt;/code&gt; context action.&lt;/p&gt;

&lt;p&gt;New commands: &lt;code&gt;acacia-db.exportHotPathReport&lt;/code&gt;, &lt;code&gt;acacia-db.hotPath.refresh&lt;/code&gt;, &lt;code&gt;acacia-db.hotPath.diagnose&lt;/code&gt;, &lt;code&gt;acacia-db.hotPath.copyIndexSuggestion&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Configuration lives under &lt;code&gt;acaciaDb.hotPath.*&lt;/code&gt;: &lt;code&gt;topN&lt;/code&gt;, &lt;code&gt;weights.usage&lt;/code&gt;, &lt;code&gt;weights.joins&lt;/code&gt;, &lt;code&gt;weights.fanOut&lt;/code&gt;, &lt;code&gt;minLinkConfidence&lt;/code&gt;, &lt;code&gt;indexSuggestionQuantile&lt;/code&gt;, &lt;code&gt;cacheCandidateQuantile&lt;/code&gt;, &lt;code&gt;cacheCandidateMaxJoinDegree&lt;/code&gt;. Changing any setting refreshes the view without a reload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Relationship-only filtering
&lt;/h3&gt;

&lt;p&gt;A new &lt;code&gt;filterToRelationshipsOnly&lt;/code&gt; setting saves only references that participate in table relationships. On large codebases this drops file size by 80–95% and is &lt;strong&gt;enabled by default&lt;/strong&gt;. Tables with zero references are no longer saved or shown.&lt;/p&gt;

&lt;p&gt;The filtering algorithm itself was rewritten: complexity went from roughly O(n² × m²) to O(n×m + f×r log r + f×r×w) by grouping references per file, sorting for early termination on proximity checks, and skipping single-table files. Filtering time on a 477-table codebase dropped from 10–20 s to 0.5–2 s. Results are cached after the first computation, so the JSON export no longer re-runs the filter.&lt;/p&gt;

&lt;h3&gt;
  
  
  File-based JSON format
&lt;/h3&gt;

&lt;p&gt;The persisted &lt;code&gt;table_refs.json&lt;/code&gt; was reorganized from table-keyed to file-keyed: each entry is a file with a list of references (&lt;code&gt;line&lt;/code&gt;, &lt;code&gt;column&lt;/code&gt;, &lt;code&gt;tableName&lt;/code&gt;). The new shape is ~40% smaller, doesn't trip &lt;code&gt;JSON.stringify&lt;/code&gt; on very large workspaces, loads faster via direct object access, and diffs cleanly in version control. Relationships are simplified to table pairs and counts.&lt;/p&gt;

&lt;p&gt;Tree-view sorting was tightened across all levels — files by reference count, relationship files by instance count, proximity instances by distance (closest first) — while the JSON keeps an alphabetical file order for stable diffs.&lt;/p&gt;




&lt;h2&gt;
  
  
  1.2.0 — Heatmap and Mermaid ER export
&lt;/h2&gt;

&lt;p&gt;1.2.0 adds two visualization paths over the data Acacia DB already collects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database Usage Heatmap
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;src/heatmapView.ts&lt;/code&gt; renders a tables × files matrix in a webview panel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SVG with a log/linear color-scale toggle and adjustable cell size.&lt;/li&gt;
&lt;li&gt;Hover tooltip showing table, file, and reference count.&lt;/li&gt;
&lt;li&gt;Click-to-open: jumps to the first line where the table appears in the file.&lt;/li&gt;
&lt;li&gt;Row totals on the right and column totals on the bottom as bar sparklines, plus a legend gradient with min/max.&lt;/li&gt;
&lt;li&gt;Driven by the in-memory &lt;code&gt;tableUsageMap&lt;/code&gt;, with &lt;code&gt;.vscode/table_refs.json&lt;/code&gt; as a no-scan fallback.&lt;/li&gt;
&lt;li&gt;Truncation warning when the matrix exceeds the configured caps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Caps are configurable: &lt;code&gt;acaciaDb.heatmap.maxTables&lt;/code&gt; (default 50, max 1000) and &lt;code&gt;acaciaDb.heatmap.maxFiles&lt;/code&gt; (default 100, max 2000). Tables and files are ranked by total reference count before truncation.&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;acacia-db.showUsageHeatmap&lt;/code&gt; is wired into the Database Explorer view title bar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mermaid ER Diagram Export
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;src/mermaidErExport.ts&lt;/code&gt; exposes a pure &lt;code&gt;buildMermaidEr&lt;/code&gt; function (no &lt;code&gt;vscode&lt;/code&gt; import) that turns detected column relationships into a Mermaid ER diagram:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Relationships are deduplicated by unordered table pair, and &lt;code&gt;forward&lt;/code&gt; / &lt;code&gt;backward&lt;/code&gt; / &lt;code&gt;bidirectional&lt;/code&gt; directions are aggregated into a single Mermaid cardinality (&lt;code&gt;}o--||&lt;/code&gt;, &lt;code&gt;||--o{&lt;/code&gt;, or &lt;code&gt;}o--o{&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Optional per-entity column blocks pulled from &lt;code&gt;tables_views.json&lt;/code&gt;, capped per table for readability.&lt;/li&gt;
&lt;li&gt;Identifiers are sanitized for Mermaid's &lt;code&gt;[A-Za-z_][A-Za-z0-9_]*&lt;/code&gt; rule; columns named &lt;code&gt;PK&lt;/code&gt; / &lt;code&gt;FK&lt;/code&gt; / &lt;code&gt;UK&lt;/code&gt; are renamed (&lt;code&gt;PK_col&lt;/code&gt;, etc.) to avoid colliding with Mermaid's reserved attribute-key tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three export targets via Quick Pick: open as Markdown preview, save to &lt;code&gt;.vscode/erDiagram.md&lt;/code&gt;, or copy Mermaid source to clipboard. The command &lt;code&gt;acacia-db.exportMermaidEr&lt;/code&gt; lives on the Column Explorer view title bar.&lt;/p&gt;

&lt;p&gt;Configuration: &lt;code&gt;acaciaDb.mermaidEr.maxTables&lt;/code&gt; (60), &lt;code&gt;acaciaDb.mermaidEr.omitIsolated&lt;/code&gt; (true), &lt;code&gt;acaciaDb.mermaidEr.includeColumns&lt;/code&gt; (true), &lt;code&gt;acaciaDb.mermaidEr.maxColumnsPerTable&lt;/code&gt; (20).&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Marketplace:&lt;/strong&gt; &lt;code&gt;manacacia.acacia-db&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/AcaciaMan/acacia-db" rel="noopener noreferrer"&gt;github.com/AcaciaMan/acacia-db&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Point it at a &lt;code&gt;tables_views.json&lt;/code&gt; and a source folder, run the analysis, and you'll get a usage tree, a relationship graph, hot-path suggestions, an ER diagram, and a heatmap — all from the same scan, all stored locally in &lt;code&gt;.vscode/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Feedback and issues welcome.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>database</category>
      <category>sql</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Building Repo Promoter Agent for the DigitalOcean Gradient™ AI Hackathon</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Thu, 09 Apr 2026 08:39:55 +0000</pubDate>
      <link>https://dev.to/acaciaman/building-repo-promoter-agent-for-the-digitalocean-gradient-ai-hackathon-32of</link>
      <guid>https://dev.to/acaciaman/building-repo-promoter-agent-for-the-digitalocean-gradient-ai-hackathon-32of</guid>
      <description>&lt;p&gt;I recently participated in the &lt;a href="https://devpost.com/software/repo-promoter-agent?ref_content=user-portfolio&amp;amp;ref_feature=in_progress" rel="noopener noreferrer"&gt;DigitalOcean Gradient™ AI Hackathon&lt;/a&gt; with a project I’m pretty excited about — &lt;strong&gt;Repo Promoter Agent&lt;/strong&gt;. The idea came from a simple but recurring problem: promoting open-source projects on GitHub is often harder than building them.&lt;/p&gt;

&lt;h3&gt;
  
  
  💡 Inspiration
&lt;/h3&gt;

&lt;p&gt;As someone who maintains several open source repositories, I noticed that my projects often struggle to reach the right audience. Writing promotional content — tweets, summaries, posts — takes time that could otherwise go into building features. I wanted a tool that could take a repository URL and instantly generate reusable marketing copy for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  🚀 What It Does
&lt;/h3&gt;

&lt;p&gt;Repo Promoter Agent does exactly that. Paste any &lt;strong&gt;public GitHub repo URL&lt;/strong&gt; into the app, and it generates a complete &lt;strong&gt;promo pack&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A catchy headline
&lt;/li&gt;
&lt;li&gt;A short summary and key benefits
&lt;/li&gt;
&lt;li&gt;Tweet-sized snippets
&lt;/li&gt;
&lt;li&gt;A LinkedIn-style post
&lt;/li&gt;
&lt;li&gt;A call to action
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All generated content is stored, indexed, and searchable — so you can quickly reuse good material across different projects.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧩 How I Built It
&lt;/h3&gt;

&lt;p&gt;The app combines several components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; A simple web UI with “Generate” and “Search” screens
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Written in &lt;strong&gt;Go&lt;/strong&gt;, it fetches repo data and structures input for the AI agent
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Layer:&lt;/strong&gt; A &lt;strong&gt;Gradient AI agent&lt;/strong&gt; processes the input and returns well‑structured JSON output
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search Engine:&lt;/strong&gt; &lt;strong&gt;Apache Solr 10&lt;/strong&gt; indexes the generated content for fast retrieval
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the agent returns the JSON promo pack, it’s stored and instantly searchable in Solr.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧠 What I Learned
&lt;/h3&gt;

&lt;p&gt;Using DigitalOcean’s &lt;strong&gt;Gradient AI platform&lt;/strong&gt; was surprisingly smooth. The key insight was to think of &lt;strong&gt;prompt design as a contract&lt;/strong&gt; — if the backend can trust the JSON format, the rest of the pipeline becomes predictable. It’s a great exercise in bridging LLM creativity with backend reliability.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ Challenges
&lt;/h3&gt;

&lt;p&gt;Getting &lt;strong&gt;Solr 10&lt;/strong&gt; configured correctly took significant tuning, especially for schema and query logic. Another tricky aspect was finding the right balance between &lt;strong&gt;AI creativity and structure&lt;/strong&gt; — ensuring the agent’s output stayed valid JSON without sounding robotic.&lt;/p&gt;

&lt;h3&gt;
  
  
  💰 Costs
&lt;/h3&gt;

&lt;p&gt;Here’s what the first day of testing looked like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App (29 hours): &lt;strong&gt;$1.07&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Droplet (34 hours): &lt;strong&gt;$1.62&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Database (58 hours): &lt;strong&gt;$1.69&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Agents: &lt;strong&gt;$0.15&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total: &lt;strong&gt;$4.53&lt;/strong&gt; for a live day of experimenting. The cost will increase as I test more agents and models.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠️ Built With
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;GitHub
&lt;/li&gt;
&lt;li&gt;Go
&lt;/li&gt;
&lt;li&gt;Solr
&lt;/li&gt;
&lt;li&gt;Gradient AI
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you want to explore the project or see it in action, check out the &lt;a href="https://devpost.com/software/repo-promoter-agent?ref_content=user-portfolio&amp;amp;ref_feature=in_progress" rel="noopener noreferrer"&gt;Devpost page here&lt;/a&gt;.&lt;/p&gt;




</description>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How can we effectively combine Go, TypeScript, Python, and WebGL in a single application?</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Thu, 02 Apr 2026 11:04:43 +0000</pubDate>
      <link>https://dev.to/acaciaman/how-can-we-effectively-combine-go-typescript-python-and-webgl-in-a-single-application-2g7g</link>
      <guid>https://dev.to/acaciaman/how-can-we-effectively-combine-go-typescript-python-and-webgl-in-a-single-application-2g7g</guid>
      <description>&lt;p&gt;I’ve been thinking about how different programming languages shine in their own areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python is perfect for scientific computation, machine learning, and quick prototyping.&lt;/li&gt;
&lt;li&gt;TypeScript dominates when building rich web or desktop apps (and has great tooling through VS Code).&lt;/li&gt;
&lt;li&gt;Go is excellent for backend services, concurrency, and deployment speed.&lt;/li&gt;
&lt;li&gt;WebGL (via JavaScript or TypeScript) makes it possible to render interactive graphics and video directly in the browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these ecosystems is powerful on its own — but real-world applications often need the strengths of several. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using Python for AI model inference,&lt;/li&gt;
&lt;li&gt;Go to handle fast concurrent servers,&lt;/li&gt;
&lt;li&gt;TypeScript/WebGL for an interactive front end.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So here’s the core question:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What are effective modern strategies, tools, or architectures for connecting these languages together in one cohesive project?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I have a few ideas, but I’d love to get insights from others who’ve built multi-language systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should something like gRPC/Protobuf be the glue between Go and Python?&lt;/li&gt;
&lt;li&gt;Can we use WebAssembly (WASM) to share logic between browser and backend?&lt;/li&gt;
&lt;li&gt;What about using message queues (e.g., Redis, Kafka) for structured language-agnostic communication?&lt;/li&gt;
&lt;li&gt;Are there practical workflows to make multi-language development not a maintenance nightmare?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any examples, open-source frameworks, or architectural patterns would be really helpful.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>programming</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Acacia Log 4.0.0 – Stop Grepping, Start Navigating Your Logs</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Tue, 24 Mar 2026 17:18:58 +0000</pubDate>
      <link>https://dev.to/acaciaman/acacia-log-400-stop-grepping-start-navigating-your-logs-bgb</link>
      <guid>https://dev.to/acaciaman/acacia-log-400-stop-grepping-start-navigating-your-logs-bgb</guid>
      <description>&lt;p&gt;Working with logs should feel like debugging, not archaeology. &lt;/p&gt;

&lt;p&gt;Most of us still scroll, grep, and mentally replay a system’s history from a flat text file where the only real structure is the &lt;strong&gt;timestamp&lt;/strong&gt; and the fact that lines arrive in order. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Acacia Log&lt;/strong&gt; is a Visual Studio Code extension that leans into that simple idea: logs are time-ordered records with timestamps, so let’s treat them as a queryable time series instead of a wall of text. &lt;/p&gt;

&lt;p&gt;Version &lt;strong&gt;4.0.0&lt;/strong&gt; is out now, and it turns that idea into a full workflow for navigating, visualizing, and comparing massive log files without leaving VS Code. &lt;/p&gt;




&lt;h2&gt;
  
  
  What is Acacia Log?
&lt;/h2&gt;

&lt;p&gt;Acacia Log is an advanced log file analyzer and visualizer for VS Code. &lt;br&gt;
It helps you navigate huge &lt;code&gt;.log&lt;/code&gt;, &lt;code&gt;.txt&lt;/code&gt;, &lt;code&gt;.jsonl&lt;/code&gt;, and &lt;code&gt;.ndjson&lt;/code&gt; files by timestamp, detect time gaps, visualize activity timelines, search with regex patterns, analyze similar lines, and compare multiple files – all inside the editor. &lt;/p&gt;

&lt;p&gt;Key capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Jump directly to any timestamp using binary search on the log’s time index. &lt;/li&gt;
&lt;li&gt;Visualize activity as interactive bar, area, or line charts with zoom and pan. &lt;/li&gt;
&lt;li&gt;Find the most frequent messages via structural “similar line” grouping. &lt;/li&gt;
&lt;li&gt;Search multiple regex patterns in parallel and see counts + charts. &lt;/li&gt;
&lt;li&gt;Compare throughput and latency across 2–20 log files. &lt;/li&gt;
&lt;li&gt;Convert between JSONL/NDJSON and plain-text logs with guided wizards. &lt;/li&gt;
&lt;li&gt;Supports 20+ timestamp formats with automatic detection (ISO, Apache, Syslog, Log4j, Windows Event Log, UNIX timestamps, and more).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your logs have timestamps and grow over time, Acacia Log treats them like a time-series you can explore.&lt;/p&gt;

&lt;p&gt;If you end up using Acacia Log 4.0.0 in your own debugging, DevOps, or performance workflows, I would love feedback to keep improving the time-based analysis features.&lt;/p&gt;




</description>
      <category>vscode</category>
      <category>analytics</category>
    </item>
    <item>
      <title>Weather‑Smart Merchandiser: Using Notion MCP + Claude to Turn DIY Sales &amp; Weather Data into Layout Actions</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Fri, 06 Mar 2026 18:41:41 +0000</pubDate>
      <link>https://dev.to/acaciaman/weather-smart-merchandiser-using-notion-mcp-claude-to-turn-diy-sales-weather-data-into-layout-2684</link>
      <guid>https://dev.to/acaciaman/weather-smart-merchandiser-using-notion-mcp-claude-to-turn-diy-sales-weather-data-into-layout-2684</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/notion-2026-03-04"&gt;Notion MCP Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;Weather‑Smart Merchandiser&lt;/strong&gt;, a weather‑driven merchandising tool that analyses historical sales–weather data, forecasts demand by temperature bucket, and then generates &lt;strong&gt;store layout‑change suggestions&lt;/strong&gt; for a DIY store.&lt;/p&gt;

&lt;p&gt;Under the hood, it’s a Python project exposed as an &lt;strong&gt;MCP server&lt;/strong&gt;, so AI assistants (like Claude Desktop) can call high‑level tools such as &lt;code&gt;layout_actions&lt;/code&gt; or &lt;code&gt;top_categories&lt;/code&gt; instead of manually running scripts. The workflow is: the assistant looks at recent DIY sales and temperatures, classifies upcoming days as cold / mild / warm, and then proposes concrete layout moves (e.g., “move garden tools to front endcap for the warm weekend” or “highlight insulation at the entrance for a cold spell”).&lt;/p&gt;

&lt;p&gt;On top of that, I use a Notion workspace as the &lt;strong&gt;control center&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A “Sales &amp;amp; Weather (Daily)” database holds the input data.
&lt;/li&gt;
&lt;li&gt;A “DIY Categories &amp;amp; Layout” database describes where each category currently lives in the store.
&lt;/li&gt;
&lt;li&gt;A “Layout Actions” database is automatically populated by the MCP tools with suggested moves, dates, and expected uplift.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a small but realistic “weather‑smart” merchandising assistant for a DIY store that feels like a real workflow, not just a toy script.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incremental updates
&lt;/h3&gt;

&lt;p&gt;I am used to develop things incrementally. As there is still time left in the challenge, I will improve the solution and in this section will write my updates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First incremental update&lt;/strong&gt;: Added a &lt;strong&gt;Kanban view&lt;/strong&gt; to the Layout Actions database in the DIY dashboard. Now store managers can instantly see actions flowing from &lt;strong&gt;Planned → In Progress → Done&lt;/strong&gt; at a glance, making the workflow feel even more production-ready.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Added SQLite database for Python MCP server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Switched from CSV to JSON data exchange format&lt;/strong&gt;: Discovered an issue. &lt;strong&gt;FastMCP&lt;/strong&gt;'s _convert_to_content function iterates over list results and converts each item separately into its own TextContent block. So when your tool returned list[dict], each dict became a separate JSON text block — producing {...}{...}{...} (concatenated objects) instead of &lt;a href="https://dev.toa%20proper%20array"&gt;{...}, {...}, {...}&lt;/a&gt;. &lt;strong&gt;The fix&lt;/strong&gt;: all three tools (demand_signals, forecast, layout_actions) now return json.dumps(result, indent=2) — a single JSON string that &lt;strong&gt;FastMCP&lt;/strong&gt; wraps in one TextContent block. Restarted Claude Desktop to pick up the change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Added Sales insights subpage in DIY dashboard&lt;/strong&gt;: Added also Claude Desktop prompt in GitHub repository to fill in Sales insights subpage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Video Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/user-attachments/assets/bdb07f87-5e2a-4974-be23-12ba47560132" rel="noopener noreferrer"&gt;https://github.com/user-attachments/assets/bdb07f87-5e2a-4974-be23-12ba47560132&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Public Notion project page:&lt;br&gt;
&lt;a href="https://neighborly-fridge-ea2.notion.site/Weather-smart-merchandiser-31a4fffb13a880618b7fd4198be66b30" rel="noopener noreferrer"&gt;https://neighborly-fridge-ea2.notion.site/Weather-smart-merchandiser-31a4fffb13a880618b7fd4198be66b30&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Public Notion DIY dashboard:&lt;br&gt;
&lt;a href="https://neighborly-fridge-ea2.notion.site/DIY-Weather-Smart-Merchandising-fffb7fe844f841bda431202321e29ac9" rel="noopener noreferrer"&gt;https://neighborly-fridge-ea2.notion.site/DIY-Weather-Smart-Merchandising-fffb7fe844f841bda431202321e29ac9&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I recorded a short video walkthrough showing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How I trigger the workflow from Claude Desktop by asking:
“Generate layout actions from Sales &amp;amp; Weather for the next 3 days and write them into Notion.”&lt;/li&gt;
&lt;li&gt;How the MCP server returns suggested actions (per store, date, category, and temperature bucket).&lt;/li&gt;
&lt;li&gt;How Claude then uses Notion’s MCP integration to create new rows in the “Layout Actions” database and generate a “Store Playbook” summary page in Notion.&lt;/li&gt;
&lt;li&gt;How I can also ask Claude to &lt;strong&gt;summarize the weekend layout actions&lt;/strong&gt; into a concise briefing, so store staff get a quick “weekend plan” without reading every individual row.&lt;/li&gt;
&lt;li&gt;The final Notion DIY dashboard that shows weather, recent sales, and planned layout changes in one place.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Show us the code
&lt;/h2&gt;

&lt;p&gt;The full source code is available here:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub repo:&lt;/strong&gt; &lt;a href="https://github.com/AcaciaMan/weather-smart-merchandiser" rel="noopener noreferrer"&gt;https://github.com/AcaciaMan/weather-smart-merchandiser&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Key pieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;first_python_module.py&lt;/code&gt; – core library with reusable functions for:

&lt;ul&gt;
&lt;li&gt;loading the &lt;code&gt;sales_weather_daily.csv&lt;/code&gt; dataset
&lt;/li&gt;
&lt;li&gt;computing demand signals by temperature bucket
&lt;/li&gt;
&lt;li&gt;generating a simple forecast
&lt;/li&gt;
&lt;li&gt;producing layout‑change suggestions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;server.py&lt;/code&gt; – MCP server entry point that wraps these functions as MCP tools.
&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;sales_weather_daily.csv&lt;/code&gt; – example dataset with Date, Store, Temp °C, Weather, Category, Units Sold, Revenue €.
&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;requirements.txt&lt;/code&gt; – Python dependencies.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;You can run it in three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As an MCP server from a client (e.g., Claude Desktop).
&lt;/li&gt;
&lt;li&gt;With an MCP inspector / dev CLI for testing.
&lt;/li&gt;
&lt;li&gt;As a standalone script to generate layout actions into &lt;code&gt;layout_actions_suggested.csv&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Used Notion MCP
&lt;/h2&gt;

&lt;p&gt;My goal was: &lt;strong&gt;say one prompt, get real layout actions written into Notion automatically, and optionally get a weekend summary.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I used Notion’s MCP integration together with my custom Python MCP server so an AI assistant can orchestrate the whole chain:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Custom MCP server (Python)&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I implemented tools such as:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;list_stores&lt;/code&gt; – list unique stores in the dataset.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;demand_signals&lt;/code&gt; – average units sold per temperature bucket and category.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top_categories&lt;/code&gt; – top sellers for cold / mild / warm conditions.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;classify_temperature&lt;/code&gt; – classify any °C value into a bucket.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;forecast&lt;/code&gt; – a simple temperature forecast for upcoming days.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;layout_actions&lt;/code&gt; – an end‑to‑end tool that takes a store and days‑ahead and returns layout suggestions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;This server runs locally and is registered as a custom MCP server in my client.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AI client (Claude Desktop) calls the MCP tools&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;From Claude, I can ask:

&lt;ul&gt;
&lt;li&gt;“For store ‘Riga 1’, generate layout actions for the next 3 days based on the existing sales_weather_daily.csv data.”
&lt;/li&gt;
&lt;li&gt;“Summarize this weekend’s layout actions into a short briefing for store staff.”
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Claude calls my &lt;code&gt;layout_actions&lt;/code&gt; tool, which:

&lt;ul&gt;
&lt;li&gt;reads the CSV (or, in a more advanced setup, reads from Notion)
&lt;/li&gt;
&lt;li&gt;computes demand signals per temperature bucket
&lt;/li&gt;
&lt;li&gt;fakes or consumes a short‑term forecast
&lt;/li&gt;
&lt;li&gt;outputs structured layout actions (Store, Start/End Date, Category, Suggested Move, Expected Uplift, Forecast Temp, Bucket).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Then, using the actions already written into Notion, I can ask Claude to &lt;strong&gt;summarize the weekend plan&lt;/strong&gt;, producing a concise natural‑language overview (“This weekend: promote Garden and Cooling near the entrance, de‑emphasize Insulation”).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Notion MCP writes the results into Notion&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the same conversation, I ask Claude to “take these layout actions and insert them into my Notion ‘Layout Actions’ database, and create a summary page.”
&lt;/li&gt;
&lt;li&gt;Using Notion’s MCP integration, Claude:

&lt;ul&gt;
&lt;li&gt;creates new rows in the &lt;strong&gt;Layout Actions&lt;/strong&gt; database (one per suggested move)
&lt;/li&gt;
&lt;li&gt;updates or creates a &lt;strong&gt;“DIY Weather‑Smart Merchandising” dashboard&lt;/strong&gt; view
&lt;/li&gt;
&lt;li&gt;generates a “Weekend Store Playbook” page summarizing:&lt;/li&gt;
&lt;li&gt;upcoming temperature buckets
&lt;/li&gt;
&lt;li&gt;key categories to promote
&lt;/li&gt;
&lt;li&gt;concrete moves for staff
&lt;/li&gt;
&lt;li&gt;a short summary of the weekend layout actions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Why Notion MCP matters here&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Notion MCP turns Notion into the &lt;strong&gt;front end&lt;/strong&gt; for the system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I don’t have to build a custom UI; everything lives in Notion pages and databases.
&lt;/li&gt;
&lt;li&gt;The AI can both &lt;strong&gt;read&lt;/strong&gt; (past actions, sales context) and &lt;strong&gt;write&lt;/strong&gt; (new layout actions, summaries) in a structured, permission‑aware way.
&lt;/li&gt;
&lt;li&gt;My Python MCP server stays focused on the “brains” (weather + sales logic), while Notion is the “workspace” where humans see and act on the plan—and even get an auto‑written weekend summary they can quickly share with the team.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>What do you do when your side project has almost no users?</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Wed, 04 Mar 2026 16:55:03 +0000</pubDate>
      <link>https://dev.to/acaciaman/what-do-you-do-when-your-side-project-has-almost-no-users-22i3</link>
      <guid>https://dev.to/acaciaman/what-do-you-do-when-your-side-project-has-almost-no-users-22i3</guid>
      <description>&lt;p&gt;Imagine you build a side project for people on the internet, but almost nobody uses it for a long time. What do you do next? Take a break, put it away, change its name, or try something else?&lt;/p&gt;

</description>
      <category>explainlikeimfive</category>
    </item>
    <item>
      <title>As AI boosts developer productivity, how will expectations change?</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Tue, 03 Mar 2026 17:04:51 +0000</pubDate>
      <link>https://dev.to/acaciaman/as-ai-boosts-developer-productivity-how-will-expectations-change-1j92</link>
      <guid>https://dev.to/acaciaman/as-ai-boosts-developer-productivity-how-will-expectations-change-1j92</guid>
      <description>&lt;p&gt;With AI accelerating coding and debugging, I’m curious how this will reshape expectations for developers. Will roles shift toward higher-level problem solving and system design, or will productivity gains mainly raise delivery pressure and standards?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>ai</category>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Bringing Local Slalom Races Online with Canoe Slalom Live</title>
      <dc:creator>Karlis</dc:creator>
      <pubDate>Sun, 01 Mar 2026 13:57:23 +0000</pubDate>
      <link>https://dev.to/acaciaman/bringing-local-slalom-races-online-with-canoe-slalom-live-4i6</link>
      <guid>https://dev.to/acaciaman/bringing-local-slalom-races-online-with-canoe-slalom-live-4i6</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the DEV Weekend Challenge: Community.&lt;/em&gt;&lt;br&gt;
​&lt;/p&gt;
&lt;h2&gt;
  
  
  The Community
&lt;/h2&gt;

&lt;p&gt;Canoe and kayak slalom has a strong grassroots scene: small clubs, volunteer judges, parents on the riverbank, and athletes who travel long distances for a single race run. Yet many local events still run on paper start lists, handwritten penalties, and spreadsheets that never leave the timing laptop.&lt;br&gt;
​&lt;/p&gt;

&lt;p&gt;I built Canoe Slalom Live for that community: local organizers who want something lightweight they can run on a single laptop at the course, judges who need a simple way to record runs, commentators who want quick access to athlete stories, and spectators who just want to understand what is happening on the water in real time.&lt;br&gt;
​&lt;/p&gt;
&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Canoe Slalom Live is a tiny live-timing and results web app for canoe/water slalom competitions. It runs as a Go web server with an embedded SQLite database and server-rendered HTML, so an organizer can start it on a laptop at the riverside and let everyone else follow the event from their phones.&lt;br&gt;
​&lt;/p&gt;

&lt;p&gt;The app provides a public event page with a start list grouped by category, a live leaderboard with penalties, a photo gallery, dedicated commentator and athlete profile views, plus a mobile-friendly judge panel for entering runs and penalties. It focuses on making results understandable for spectators while giving judges and commentators tools that fit how small events actually work.&lt;br&gt;
​&lt;br&gt;
It’s a single Go + SQLite binary that can run on a small VPS or services like Google Cloud Run.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;GitHub repository (code + README + screenshots):&lt;br&gt;


&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/AcaciaMan" rel="noopener noreferrer"&gt;
        AcaciaMan
      &lt;/a&gt; / &lt;a href="https://github.com/AcaciaMan/canoe-slalom-live" rel="noopener noreferrer"&gt;
        canoe-slalom-live
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Weekend-built sports app for canoe/water slalom meets. Supports creating events, managing start lists and athlete bios, recording runs and penalties, and showing a live leaderboard for the whole community.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🛶 Canoe Slalom Live&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Live timing and results for canoe/water slalom competitions. Built for grassroots events — run it on a laptop at the riverside, let spectators follow on their phones.&lt;/p&gt;
&lt;p&gt;Short introduction video
&lt;a href="https://github.com/user-attachments/assets/90fe481d-032e-493f-acd4-5c0e1be7cca1" rel="noopener noreferrer"&gt;https://github.com/user-attachments/assets/90fe481d-032e-493f-acd4-5c0e1be7cca1&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Quick Start&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Prerequisites: Go 1.22+, GCC (for SQLite CGo driver)&lt;/span&gt;
go mod tidy
go run main.go -seed

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Opens at http://localhost:8080&lt;/span&gt;
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Judge panel at http://localhost:8080/judge/events/demo-slalom-2026&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;To enable authentication for judge routes:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Windows&lt;/span&gt;
&lt;span class="pl-c1"&gt;set&lt;/span&gt; ADMIN_TOKEN=secret123
go run main.go -seed

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Linux/macOS&lt;/span&gt;
ADMIN_TOKEN=secret123 go run main.go -seed

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Judge panel: http://localhost:8080/judge/events/demo-slalom-2026?token=secret123&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Stack&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Go&lt;/strong&gt; — &lt;code&gt;net/http&lt;/code&gt; with Go 1.22+ pattern routing, &lt;code&gt;html/template&lt;/code&gt; for server-rendered HTML&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; — embedded via &lt;code&gt;github.com/mattn/go-sqlite3&lt;/code&gt; (CGo), WAL mode, single &lt;code&gt;data.db&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vanilla HTML/CSS/JS&lt;/strong&gt; — no build step, no framework, no bundler&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s a single Go + SQLite binary that can run on a small VPS or services like Google Cloud Run.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Pages&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Route&lt;/th&gt;
&lt;th&gt;Page&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/events/{slug}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Event&lt;/td&gt;
&lt;td&gt;Start list grouped&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/AcaciaMan/canoe-slalom-live" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;p&gt;Short intro video (live walk-through of the seeded demo event):&lt;br&gt;
&lt;a href="https://github.com/user-attachments/assets/90fe481d-032e-493f-acd4-5c0e1be7cca1" rel="noopener noreferrer"&gt;https://github.com/user-attachments/assets/90fe481d-032e-493f-acd4-5c0e1be7cca1&lt;/a&gt;&lt;br&gt;
​&lt;/p&gt;

&lt;p&gt;To try it locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bash
go mod tidy
go run main.go -seed
# Opens at http://localhost:8080
# Judge panel at http://localhost:8080/judge/events/demo-slalom-2026
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;The full source code is available here:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/AcaciaMan" rel="noopener noreferrer"&gt;
        AcaciaMan
      &lt;/a&gt; / &lt;a href="https://github.com/AcaciaMan/canoe-slalom-live" rel="noopener noreferrer"&gt;
        canoe-slalom-live
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Weekend-built sports app for canoe/water slalom meets. Supports creating events, managing start lists and athlete bios, recording runs and penalties, and showing a live leaderboard for the whole community.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🛶 Canoe Slalom Live&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;Live timing and results for canoe/water slalom competitions. Built for grassroots events — run it on a laptop at the riverside, let spectators follow on their phones.&lt;/p&gt;

&lt;p&gt;Short introduction video
&lt;a href="https://github.com/user-attachments/assets/90fe481d-032e-493f-acd4-5c0e1be7cca1" rel="noopener noreferrer"&gt;https://github.com/user-attachments/assets/90fe481d-032e-493f-acd4-5c0e1be7cca1&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Quick Start&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Prerequisites: Go 1.22+, GCC (for SQLite CGo driver)&lt;/span&gt;
go mod tidy
go run main.go -seed

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Opens at http://localhost:8080&lt;/span&gt;
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Judge panel at http://localhost:8080/judge/events/demo-slalom-2026&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;To enable authentication for judge routes:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Windows&lt;/span&gt;
&lt;span class="pl-c1"&gt;set&lt;/span&gt; ADMIN_TOKEN=secret123
go run main.go -seed

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Linux/macOS&lt;/span&gt;
ADMIN_TOKEN=secret123 go run main.go -seed

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Judge panel: http://localhost:8080/judge/events/demo-slalom-2026?token=secret123&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Stack&lt;/h2&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Go&lt;/strong&gt; — &lt;code&gt;net/http&lt;/code&gt; with Go 1.22+ pattern routing, &lt;code&gt;html/template&lt;/code&gt; for server-rendered HTML&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; — embedded via &lt;code&gt;github.com/mattn/go-sqlite3&lt;/code&gt; (CGo), WAL mode, single &lt;code&gt;data.db&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vanilla HTML/CSS/JS&lt;/strong&gt; — no build step, no framework, no bundler&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a single Go + SQLite binary that can run on a small VPS or services like Google Cloud Run.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Pages&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Route&lt;/th&gt;

&lt;th&gt;Page&lt;/th&gt;

&lt;th&gt;Description&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;&lt;code&gt;/events/{slug}&lt;/code&gt;&lt;/td&gt;

&lt;td&gt;Event&lt;/td&gt;

&lt;td&gt;Start list grouped&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;…&lt;p&gt;&lt;/p&gt;&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/AcaciaMan/canoe-slalom-live" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
​&lt;/p&gt;

&lt;p&gt;Key routes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/events/{slug} – event overview with start list and athlete bios&lt;/li&gt;
&lt;li&gt;/events/{slug}/leaderboard – live leaderboard with auto-refresh and penalty sparklines&lt;/li&gt;
&lt;li&gt;/events/{slug}/photos – photo gallery with photographer credits&lt;/li&gt;
&lt;li&gt;/events/{slug}/commentator – big-screen commentator view&lt;/li&gt;
&lt;li&gt;/events/{slug}/athletes/{id} – athlete profile with run history and linked photos&lt;/li&gt;
&lt;li&gt;/judge/events/{slug} – judge panel for recording runs (auth-protected via admin token) ​&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;Stack and architecture&lt;br&gt;
I used Go 1.22 with net/http pattern routing and html/template for fully server-rendered pages, backed by a single SQLite database file accessed through github.com/mattn/go-sqlite3. There is no build pipeline or frontend framework: just vanilla HTML, CSS, and a tiny bit of JavaScript for auto-refresh.&lt;br&gt;
​&lt;/p&gt;

&lt;p&gt;The project is split into small packages: domain for core types (events, athletes, runs, sponsors, photos), store for SQLite queries, and handler for public and judge HTTP handlers plus authentication and logging middleware. Templates live in templates/ and are composed around a shared layout with a simple nav bar linking Event, Leaderboard, Photos, and Judge.&lt;br&gt;
​&lt;/p&gt;

&lt;h2&gt;
  
  
  Data model and scoring
&lt;/h2&gt;

&lt;p&gt;The SQLite schema has seven tables: events, categories, athletes, entries, runs, sponsors, and photos. Entries link athletes to an event and category with a bib number; runs store raw time, touches, missed gates, and computed total time, and a UNIQUE(entry_id, run_number) constraint prevents duplicate runs. Scoring follows standard ICF rules: +2 seconds per gate touch, +50 seconds per missed gate, ranking athletes by their best single-run total time.&lt;br&gt;
​&lt;/p&gt;

&lt;h2&gt;
  
  
  UX for each role
&lt;/h2&gt;

&lt;p&gt;For spectators, the leaderboard auto-refreshes every 10 seconds and highlights medals, “NEW” runs, time-behind-leader, and tiny CSS sparklines that compare raw time vs penalties. Commentators get a dedicated view that shows the latest result in huge type with bio and penalties plus current top three for each category, optimized for projection. Judges use a mobile-friendly panel with large tap targets, penalty steppers, confirmation before saving, recent runs, and run-status indicators so they can work quickly in a noisy outdoor environment.&lt;br&gt;
​&lt;/p&gt;

&lt;h2&gt;
  
  
  Safety and polish
&lt;/h2&gt;

&lt;p&gt;To keep things safe without overbuilding auth, judge routes are protected with an ADMIN_TOKEN environment variable and a simple session cookie once the token is used. There is server-side validation for time ranges and maximum penalties, basic security headers, and structured request logging with method, path, status, and duration. I also seeded a complete demo event (Demo Slalom 2026) so anyone cloning the repo can see realistic data, categories, and sponsors immediately&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
