<?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: opensource</title>
    <description>The latest articles tagged 'opensource' on DEV Community.</description>
    <link>https://dev.to/t/opensource</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tag/opensource"/>
    <language>en</language>
    <item>
      <title>My Hacktoberfest 2026 Journey: Getting Started with Open Source</title>
      <dc:creator>Ayush Aryan</dc:creator>
      <pubDate>Tue, 13 Oct 2026 20:03:59 +0000</pubDate>
      <link>https://dev.to/ayusharyan4269bit/my-hacktoberfest-2026-journey-getting-started-with-open-source-43no</link>
      <guid>https://dev.to/ayusharyan4269bit/my-hacktoberfest-2026-journey-getting-started-with-open-source-43no</guid>
      <description>&lt;h1&gt;
  
  
  My Hacktoberfest 2026 Journey: Getting Started with Open Source
&lt;/h1&gt;

&lt;p&gt;Hey everyone!&lt;/p&gt;

&lt;p&gt;I'm a Computer Science undergraduate at IIIT Lucknow, and I've been spending time learning programming, solving DSA problems, and building projects.&lt;/p&gt;

&lt;p&gt;Now, I want to take the next step by contributing to open source.&lt;/p&gt;

&lt;p&gt;Hacktoberfest feels like a good opportunity to explore real-world projects, understand how developers collaborate, and learn how software is built beyond personal projects and tutorials.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Want to Learn
&lt;/h2&gt;

&lt;p&gt;Here are a few things I want to focus on during this journey:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exploring open-source repositories and understanding their codebases.&lt;/li&gt;
&lt;li&gt;Finding issues where I can make meaningful contributions.&lt;/li&gt;
&lt;li&gt;Improving my Git and GitHub workflow, especially branches and pull requests.&lt;/li&gt;
&lt;li&gt;Learning how to read existing code and debug unfamiliar projects.&lt;/li&gt;
&lt;li&gt;Connecting with developers and learning from their experiences.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technologies I'm Interested In
&lt;/h2&gt;

&lt;p&gt;My current interests include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C++ and Data Structures &amp;amp; Algorithms&lt;/li&gt;
&lt;li&gt;React and Next.js&lt;/li&gt;
&lt;li&gt;Web Development&lt;/li&gt;
&lt;li&gt;Web3 and Blockchain Development&lt;/li&gt;
&lt;li&gt;AI-powered applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm happy to explore projects outside these areas if they offer an opportunity to learn something new.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking for Recommendations
&lt;/h2&gt;

&lt;p&gt;Since I'm getting more involved in open source, I'd appreciate recommendations for repositories that welcome new contributors.&lt;/p&gt;

&lt;p&gt;I'd love to hear about your experiences and learn from the community.&lt;/p&gt;

&lt;p&gt;My goal is to make genuine contributions, improve my development skills, and become more comfortable working on collaborative projects.&lt;/p&gt;

&lt;p&gt;Looking forward to seeing what I can learn along the way.&lt;/p&gt;

&lt;h1&gt;
  
  
  hacktoberfest #opensource #beginners
&lt;/h1&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>opensource</category>
      <category>react</category>
    </item>
    <item>
      <title>New stricter rules from GitHub for code packages after security investigation</title>
      <dc:creator>Hacks.gr</dc:creator>
      <pubDate>Tue, 13 Oct 2026 20:01:21 +0000</pubDate>
      <link>https://dev.to/hacksgr/new-stricter-rules-from-github-for-code-packages-after-security-investigation-1j5</link>
      <guid>https://dev.to/hacksgr/new-stricter-rules-from-github-for-code-packages-after-security-investigation-1j5</guid>
      <description>&lt;p&gt;GitHub has added a 48-hour expiration window for unvalidated npm trusted publishing configurations, closing a supply chain loophole that allowed attackers to claim abandoned repository slugs and publish package updates without credentials.&lt;/p&gt;




&lt;p&gt;The issue was discovered by security firm Bloom Security, which notified GitHub on June 6, 2026. According to the researchers, the vulnerability arose from the way the platform identified which code repository belonged to whom. Specifically, the system relied on the name of the address rather than a permanent digital identifier.&lt;/p&gt;

&lt;p&gt;This meant that if an address name was left blank, a skilled attacker could figure it out. In this way, they could gain the trust of the system and publish malicious changes to software they did not own, taking advantage of the reputation and downloads of the original package. The research identified more than 1.500 vulnerable packages that had been downloaded a total of over 10 million times.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's changing in software publishing
&lt;/h2&gt;

&lt;p&gt;To address this issue, GitHub has decided that trust settings that have not been validated with a successful publish will now automatically expire within 48 hours of their creation. Each setting becomes permanent once the first publish is successfully completed, while if the project identity changes, a new process is required with a new 48-hour window.&lt;/p&gt;

&lt;p&gt;Additionally, npm rejects requests originating from certain automated code comment and request processes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should creators do?
&lt;/h2&gt;

&lt;p&gt;Software creators who manage packages are asked to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;check the settings of trusted connections,&lt;/li&gt;
&lt;li&gt;delete and recreate links if repositories are renamed or moved,&lt;/li&gt;
&lt;li&gt;monitor for any unexpected posts.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://en.hacks.gr/neoi-aystiroteroi-kanones-apo-ti-github-gia-paketa-kodika-meta-apo-ereyna-asfaleias/" rel="noopener noreferrer"&gt;Read the original English article on Hacks.gr&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>npm</category>
      <category>supplychain</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Argon2id Security for Self-Hosted AI Wallets: CLI Master Password Best Practices</title>
      <dc:creator>Wallet Guy</dc:creator>
      <pubDate>Tue, 13 Oct 2026 19:51:21 +0000</pubDate>
      <link>https://dev.to/walletguy/argon2id-security-for-self-hosted-ai-wallets-cli-master-password-best-practices-508h</link>
      <guid>https://dev.to/walletguy/argon2id-security-for-self-hosted-ai-wallets-cli-master-password-best-practices-508h</guid>
      <description>&lt;h1&gt;
  
  
  Argon2id Security for Self-Hosted AI Wallets: CLI Master Password Best Practices
&lt;/h1&gt;

&lt;p&gt;Self-hosted AI wallets live or die by one question: who controls the master password? If you're running WAIaaS on your own server, you've already made the right call by keeping your AI agent's private keys off someone else's infrastructure — but that decision only pays off if the password protecting those keys is treated with the same seriousness as the keys themselves. This post walks through exactly how WAIaaS handles master password security and what you should do to harden it from day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the Master Password Is the Root of Everything
&lt;/h2&gt;

&lt;p&gt;In a self-hosted wallet setup, the master password isn't just an admin credential — it's the cryptographic root from which everything else derives. WAIaaS uses Argon2id to protect it, which is the current best-practice algorithm for password hashing. Argon2id is memory-hard, meaning brute-force attacks are expensive in both time and RAM, not just CPU cycles. That matters enormously when your wallet is internet-accessible, even behind a VPN.&lt;/p&gt;

&lt;p&gt;The master password gates the &lt;code&gt;masterAuth&lt;/code&gt; layer — one of three distinct authentication methods in WAIaaS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;masterAuth&lt;/strong&gt; (Argon2id) — system administrator: creates wallets, manages sessions, sets policies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ownerAuth&lt;/strong&gt; (SIWS/SIWE) — fund owner: approves transactions, uses the kill switch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sessionAuth&lt;/strong&gt; (JWT HS256) — AI agents: executes transactions within policy bounds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your AI agent never touches the master password. It operates on short-lived session tokens. The master password is only needed for administrative operations: provisioning wallets, setting policies, and creating those session tokens. That separation is intentional and important. Compromise a session token and an attacker is bounded by your policies. Compromise the master password and it's a different conversation entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Auto-Provision Path: Getting Started Without Foot Guns
&lt;/h2&gt;

&lt;p&gt;If you're spinning up WAIaaS for the first time, the &lt;code&gt;--auto-provision&lt;/code&gt; flag is your friend. It generates a cryptographically random master password on first start and writes it to a recovery file, so you don't have to invent a password under pressure during setup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @waiaas/cli
waiaas init &lt;span class="nt"&gt;--auto-provision&lt;/span&gt;     &lt;span class="c"&gt;# Generates random master password → recovery.key&lt;/span&gt;
waiaas start                     &lt;span class="c"&gt;# No password prompt&lt;/span&gt;
waiaas quickset                  &lt;span class="c"&gt;# Creates wallets + sessions automatically&lt;/span&gt;
waiaas set-master                &lt;span class="c"&gt;# (Later) Harden password, then delete recovery.key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last step — &lt;code&gt;waiaas set-master&lt;/code&gt; — is critical and easy to skip. The auto-generated password in &lt;code&gt;recovery.key&lt;/code&gt; is strong, but it's sitting on disk in plaintext. Your hardening checklist after initial setup should be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;waiaas set-master&lt;/code&gt; to replace the auto-generated password with one you've chosen and can store in a proper secret manager&lt;/li&gt;
&lt;li&gt;Verify the new password works by running a test command (e.g., &lt;code&gt;waiaas status&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Delete &lt;code&gt;recovery.key&lt;/code&gt; from disk&lt;/li&gt;
&lt;li&gt;Store the new password in a password manager or hardware-backed secret store — never in a &lt;code&gt;.env&lt;/code&gt; file committed to version control&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The same pattern applies to Docker deployments. Auto-provision works identically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; waiaas &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1:3100:3100 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; waiaas-data:/data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;WAIAAS_AUTO_PROVISION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/waiaas/waiaas:latest

&lt;span class="c"&gt;# Retrieve auto-generated master password&lt;/span&gt;
docker &lt;span class="nb"&gt;exec &lt;/span&gt;waiaas &lt;span class="nb"&gt;cat&lt;/span&gt; /data/recovery.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After retrieving that key, treat it like a root SSH key: copy it somewhere safe, then replace it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker Secrets: The Production-Grade Approach
&lt;/h2&gt;

&lt;p&gt;Environment variables are convenient but they leak. They show up in &lt;code&gt;docker inspect&lt;/code&gt;, in process tables, in container logs if you're not careful. For a self-hosted setup that you're actually going to trust with real funds, Docker Secrets is the right tool.&lt;/p&gt;

&lt;p&gt;WAIaaS's Docker entrypoint supports Docker Secrets natively, and there's a dedicated &lt;code&gt;docker-compose.secrets.yml&lt;/code&gt; overlay for production deployments. The workflow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create secret files&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; secrets
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"your-secure-password"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; secrets/master_password.txt
&lt;span class="nb"&gt;chmod &lt;/span&gt;600 secrets/master_password.txt

&lt;span class="c"&gt;# Deploy with secrets overlay&lt;/span&gt;
docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.secrets.yml up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;600&lt;/code&gt; permissions on the secrets file matter. It means only the owning user can read it — not other users on the same system, not processes running as different UIDs. The WAIaaS Docker image itself runs as UID 1001 (non-root), which means even if something inside the container misbehaves, it can't escalate to root to read files it shouldn't.&lt;/p&gt;

&lt;p&gt;The base Docker Compose configuration for reference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;daemon&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/waiaas/waiaas:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;waiaas-daemon&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;127.0.0.1:3100:3100"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;waiaas-data:/data&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;WAIAAS_DATA_DIR=/data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;WAIAAS_DAEMON_HOSTNAME=0.0.0.0&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CMD"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;curl"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-f"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:3100/health"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;
      &lt;span class="na"&gt;start_period&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
      &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;waiaas-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the port binding: &lt;code&gt;127.0.0.1:3100:3100&lt;/code&gt;. That's loopback-only by default, which means the API is not exposed to your network unless you explicitly make it so. If you need remote access, put a reverse proxy with TLS in front of it rather than changing the bind address to &lt;code&gt;0.0.0.0&lt;/code&gt; directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  What masterAuth Actually Protects
&lt;/h2&gt;

&lt;p&gt;It helps to be concrete about what operations require the master password, because that scope defines your threat model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a wallet (masterAuth)&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/wallets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "trading-wallet", "chain": "solana", "environment": "mainnet"}'&lt;/span&gt;

&lt;span class="c"&gt;# Create a session for AI agent (masterAuth)&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/sessions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"walletId": "&amp;lt;wallet-uuid&amp;gt;"}'&lt;/span&gt;

&lt;span class="c"&gt;# Create policy (masterAuth)&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once wallets, sessions, and policies are set up, your AI agent operates entirely on its session token. The master password doesn't appear in any agent workflow. This is by design — you do your administrative work, lock down the master password in your secret manager, and your agent runs without ever needing it.&lt;/p&gt;

&lt;p&gt;The session token gets passed as a standard Bearer token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check wallet balance (sessionAuth)&lt;/span&gt;
curl http://127.0.0.1:3100/v1/wallet/balance &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_eyJhbGciOiJIUzI1NiJ9..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That session token has its own security properties: per-session TTL, &lt;code&gt;maxRenewals&lt;/code&gt;, and &lt;code&gt;absoluteLifetime&lt;/code&gt; controls. If a session token is compromised, you revoke it without touching the master password. The blast radius is bounded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Policy as Defense-in-Depth
&lt;/h2&gt;

&lt;p&gt;Even with a strong master password and properly isolated session tokens, you want policies acting as a backstop. WAIaaS has a policy engine with 21 policy types and a default-deny stance — transactions are blocked unless explicitly allowed.&lt;/p&gt;

&lt;p&gt;The most important policy to set early is &lt;code&gt;SPENDING_LIMIT&lt;/code&gt;, which maps to the four security tiers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;INSTANT&lt;/strong&gt; — execute immediately&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NOTIFY&lt;/strong&gt; — execute immediately, send notification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DELAY&lt;/strong&gt; — queue for N seconds, then execute (cancellable window)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APPROVAL&lt;/strong&gt; — require human approval via WalletConnect or Telegram&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a self-hosted setup where you're the only operator, you might start conservative:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/policies &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Master-Password: my-secret-password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "walletId": "&amp;lt;wallet-uuid&amp;gt;",
    "type": "SPENDING_LIMIT",
    "rules": {
      "instant_max_usd": 100,
      "notify_max_usd": 500,
      "delay_max_usd": 2000,
      "delay_seconds": 900,
      "daily_limit_usd": 5000
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these rules, anything under $100 executes immediately. $100-$500 executes but you get notified. $500-$2,000 sits in a queue for 15 minutes — you can cancel it. Above $2,000, your agent can't proceed without you explicitly approving it via WalletConnect or a signing channel. That's a meaningful safety net even if a session token were somehow misused.&lt;/p&gt;

&lt;p&gt;You can also dry-run any transaction before it touches the network, which is useful during setup to verify your policies are behaving as expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:3100/v1/transactions/send &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer wai_sess_&amp;lt;token&amp;gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "type": "TRANSFER",
    "to": "recipient-address",
    "amount": "0.1",
    "dryRun": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Self-Hosted Philosophy in Practice
&lt;/h2&gt;

&lt;p&gt;Running your own wallet infrastructure is the crypto equivalent of hosting your own email server, but WAIaaS makes it genuinely practical rather than a weekend project that never quite works. One Docker command gets you a daemon with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Argon2id master password hashing&lt;/li&gt;
&lt;li&gt;Non-root container execution (UID 1001)&lt;/li&gt;
&lt;li&gt;Docker Secrets support&lt;/li&gt;
&lt;li&gt;Health checks&lt;/li&gt;
&lt;li&gt;Loopback-only port binding by default&lt;/li&gt;
&lt;li&gt;Named volume data persistence
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/waiaas/WAIaaS.git
&lt;span class="nb"&gt;cd &lt;/span&gt;WAIaaS
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You own the data directory. You own the keys. There's no hosted service receiving your transaction history, no third-party API key required to make basic wallet operations work. The tradeoff is that you're responsible for your own backups (WAIaaS has &lt;code&gt;backup create&lt;/code&gt;, &lt;code&gt;backup list&lt;/code&gt;, and &lt;code&gt;restore&lt;/code&gt; CLI commands for this) and your own uptime. For most self-hosters on community forums like r/selfhosted and r/homelab, that tradeoff is exactly the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Hardening Checklist
&lt;/h2&gt;

&lt;p&gt;If you're setting up WAIaaS today, here's the condensed version:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use auto-provision first&lt;/strong&gt;, then immediately run &lt;code&gt;waiaas set-master&lt;/code&gt; to replace the generated password with one stored in your password manager&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete &lt;code&gt;recovery.key&lt;/code&gt;&lt;/strong&gt; after confirming your new password works&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Docker Secrets&lt;/strong&gt; (&lt;code&gt;docker-compose.secrets.yml&lt;/code&gt;) rather than passing the master password as an environment variable in production&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the port binding loopback-only&lt;/strong&gt; (&lt;code&gt;127.0.0.1:3100:3100&lt;/code&gt;) and put TLS in front via a reverse proxy if you need remote access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set a &lt;code&gt;SPENDING_LIMIT&lt;/code&gt; policy&lt;/strong&gt; before your agent starts executing transactions — default-deny means your agent can't do anything without explicit permission anyway, but limits give you a time window to react if something goes wrong&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create session tokens with appropriate TTLs&lt;/strong&gt; using &lt;code&gt;waiaas set-master&lt;/code&gt; to configure session lifetime parameters — a session token with a short TTL limits exposure windows&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The CLI gives you 20 commands covering the full lifecycle from &lt;code&gt;init&lt;/code&gt; through &lt;code&gt;backup&lt;/code&gt; and &lt;code&gt;restore&lt;/code&gt;. The &lt;code&gt;status&lt;/code&gt; and &lt;code&gt;wallet info&lt;/code&gt; commands are useful for verifying your setup is in the state you think it's in before you hand session tokens to an agent.&lt;/p&gt;

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

&lt;p&gt;The security model described here — Argon2id master auth, session-scoped agent tokens, policy-gated transactions — is the foundation everything else in WAIaaS builds on. Once you have a hardened self-hosted instance running, the natural next steps are connecting it to your AI agent via MCP or the TypeScript/Python SDKs, and configuring DeFi policies for the specific protocols your agent will interact with.&lt;/p&gt;

&lt;p&gt;If you want to dig into the full setup or read the source, everything is at &lt;a href="https://github.com/waiaas/WAIaaS" rel="noopener noreferrer"&gt;https://github.com/waiaas/WAIaaS&lt;/a&gt;. The project site with documentation is at &lt;a href="https://waiaas.ai" rel="noopener noreferrer"&gt;https://waiaas.ai&lt;/a&gt;. No hosted service required — you've got the keys.&lt;/p&gt;

</description>
      <category>security</category>
      <category>selfhosted</category>
      <category>cli</category>
      <category>opensource</category>
    </item>
    <item>
      <title>ProofCheck: checking UPI payment screenshots against the bank statement, on your own laptop</title>
      <dc:creator>TEJAS _</dc:creator>
      <pubDate>Tue, 13 Oct 2026 19:49:49 +0000</pubDate>
      <link>https://dev.to/jx777/proofcheck-checking-upi-payment-screenshots-against-the-bank-statement-on-your-own-laptop-4hgl</link>
      <guid>https://dev.to/jx777/proofcheck-checking-upi-payment-screenshots-against-the-bank-statement-on-your-own-laptop-4hgl</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&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%2Fs9xa4zop5s98d1m4d772.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%2Fs9xa4zop5s98d1m4d772.png" alt="ProofCheck's report on the demo data: verified payments, missing ones, an edited amount, a duplicate, and who has paid" width="800" height="727"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;If you've ever paid a tuition fee, a society maintenance bill or a home baker in India, you know how it goes. You pay by UPI, take a screenshot, send it on WhatsApp. Done.&lt;/p&gt;

&lt;p&gt;Now think about the person on the other end. A tuition teacher with 40 students gets 40 screenshots a month, at random times, buried in the rest of her WhatsApp. At some point she sits down with her bank statement and ticks them off one by one, reading 12-digit reference numbers off a phone screen.&lt;/p&gt;

&lt;p&gt;And she can't fully trust any of them. A screenshot is just a picture. It can be edited. It can be of a payment that failed. It can be last month's screenshot sent again. Fake payment screenshots are a common enough scam that banks and payment companies keep publishing guides telling shopkeepers to check their account, not the screenshot.&lt;/p&gt;

&lt;p&gt;That check is the whole tool. ProofCheck takes a folder of payment screenshots and a bank statement export, reads the UPI reference number (the UTR) off each screenshot, and looks for it in the statement. Every screenshot ends up as one of these:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Verified&lt;/td&gt;
&lt;td&gt;The UTR is in the statement and the amount matches. The money came in.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amount differs&lt;/td&gt;
&lt;td&gt;The UTR is there, but the screenshot shows a different amount.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Not in statement&lt;/td&gt;
&lt;td&gt;No such UTR. Could be fake, could be a payment that hasn't settled yet.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplicate&lt;/td&gt;
&lt;td&gt;Another screenshot already used this UTR.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outside dates&lt;/td&gt;
&lt;td&gt;The screenshot is dated after the statement ends. Check a newer statement.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unreadable&lt;/td&gt;
&lt;td&gt;Couldn't find a UTR. You'll have to look at this one yourself.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You'll notice it never says "fake". I went back and forth on that. A missing UTR is suspicious, but a payment made an hour ago is missing too, and accusing a parent of fraud over a settlement delay is a good way to lose a student.&lt;/p&gt;

&lt;p&gt;Give it a small roster as well (who owes how much, and who usually pays for them) and you get the list a teacher actually cares about on the 5th of the month: who has paid, who paid part, who only sent a screenshot, and who hasn't paid at all. Money that arrived without any screenshot still counts, because the statement is the source of truth, not WhatsApp.&lt;/p&gt;

&lt;p&gt;So who would pay for this? Anyone collecting the same payments every month into a personal account and matching them by hand. Tuition classes are the obvious case. Housing society treasurers are another: a 120-flat society has 120 maintenance payments to match every month, often in a spreadsheet. The amounts are small, so the tool has to cost almost nothing to run, and that's a big part of why it's built on open models.&lt;/p&gt;

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

&lt;p&gt;The demo data is a made-up tuition class collecting October fees. There are eight screenshots, and between them they cover every case: payments that went through, one that never arrived, a failed payment sent as proof, a screenshot where ₹200 was edited to ₹2,000, and the same screenshot sent twice for two kids.&lt;/p&gt;

&lt;p&gt;Results show up row by row while it's still reading:&lt;/p&gt;

&lt;p&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%2Fz5lcs64p8w1kdqocn6tk.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%2Fz5lcs64p8w1kdqocn6tk.png" alt="Rows appearing while the screenshots are still being read" width="799" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On my laptop (a GTX 1650 with 4 GB of VRAM, nothing fancy) it got all 8 screenshots and all 8 roster lines right. With the model already loaded, the run took about 94 seconds, so roughly 12 seconds a screenshot.&lt;/p&gt;

&lt;p&gt;What that does and doesn't prove: the demo data is synthetic, so it shows the pipeline works end to end. It says nothing yet about how well it reads real screenshots from real phones.&lt;/p&gt;

&lt;p&gt;About those demo screenshots. They come from a fake app I called "Demo Pay", with SAMPLE - NOT A REAL PAYMENT stamped across them. It felt wrong to build a tool that catches fake payment screenshots and then ship a folder of convincing fake payment screenshots with it.&lt;/p&gt;

&lt;p&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%2Fzucxam4bem484hxa4bmu.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%2Fzucxam4bem484hxa4bmu.png" alt="A demo screenshot of a failed payment, watermarked as sample data" width="720" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to run it yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull gemma3:4b
&lt;span class="nb"&gt;cd &lt;/span&gt;frontend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm ci &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run build &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;span class="nb"&gt;cd &lt;/span&gt;backend &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; uv &lt;span class="nb"&gt;sync&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; uv run proofcheck   &lt;span class="c"&gt;# then open http://127.0.0.1:8000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&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/Surge77" rel="noopener noreferrer"&gt;
        Surge77
      &lt;/a&gt; / &lt;a href="https://github.com/Surge77/proofcheck" rel="noopener noreferrer"&gt;
        proofcheck
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Check UPI payment screenshots against your bank statement with local open-weight models (Gemma + RapidOCR). Your statement never leaves your laptop.
    &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;ProofCheck&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Check UPI payment screenshots against your bank statement, on your own laptop.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tuition teachers, housing-society treasurers, home bakers and tiffin services collect payments
by UPI into a personal account. The "proof" arrives as a screenshot on WhatsApp, and every month
someone matches dozens of them against the bank statement by hand. Fake payment screenshots are a
common scam, and they look exactly like real ones.&lt;/p&gt;
&lt;p&gt;ProofCheck reads each screenshot with local open-weight models, finds its 12-digit UPI reference
(UTR), and looks for that reference in your bank statement. It then tells you, in plain words
who really paid.&lt;/p&gt;
&lt;p&gt;Nothing is uploaded anywhere. The models run on your machine, uploads stay in memory, and your
bank statement never leaves your laptop.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Surge77/proofcheck/docs/report.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FSurge77%2Fproofcheck%2FHEAD%2Fdocs%2Freport.png" alt="ProofCheck report on the demo data: 3 verified, 2 not in statement, 1 amount differs, 1 duplicate, 1 outside dates, and who has paid"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What it tells you&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;Result&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Verified&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The UTR is in your statement with the same amount. The money arrived.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Amount differs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The UTR is there, but the screenshot&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/Surge77/proofcheck" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;screenshot ──► RapidOCR ─────► exact characters ─┐
     │                                           ├─► cross-check ─► receipt (high / low confidence)
     └───────► Gemma 3 4B ───► what they mean ───┘                       │
bank statement (CSV / XLS / XLSX) ──► credits with UTR, payer, UPI id ──► reconcile ─► report
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hard part is reading the screenshot. A typical payment screen has a phone number, a transaction ID, a date and the UTR all in one place, and a phone number with the 91 prefix is also 12 digits.&lt;/p&gt;

&lt;p&gt;I ended up using two open models and making them check each other.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/RapidAI/RapidOCR" rel="noopener noreferrer"&gt;RapidOCR&lt;/a&gt;, which runs PaddleOCR's models on onnxruntime, reads the text exactly, character by character. It has no idea which number is the UTR, though.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ai.google.dev/gemma" rel="noopener noreferrer"&gt;Gemma 3 4B&lt;/a&gt;, running locally in Ollama, looks at the same screenshot and understands it. It can tell the UTR from the phone number, and "Payment Successful" from "Payment Failed". What it can't always do is read twelve small digits perfectly.&lt;/p&gt;

&lt;p&gt;So neither of them gets the final say. When Gemma says "this is the UTR", ProofCheck only accepts it if OCR saw exactly the same digits:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_fuse_utr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vision_utr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;seen_by_ocr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;utr_candidates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
    &lt;span class="n"&gt;claimed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\s&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vision_utr&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;claimed&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seen_by_ocr&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;claimed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;          &lt;span class="c1"&gt;# both models agree
&lt;/span&gt;    &lt;span class="n"&gt;fallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_ocr_utr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;        &lt;span class="c1"&gt;# a single labelled OCR candidate, or nothing
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;claimed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;issues&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;The vision model&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s UTR was not confirmed by OCR; please check it.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;issues&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;Could not tell which number is the UPI reference.&lt;/span&gt;&lt;span class="sh"&gt;"&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;fallback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The amount, the payment status and the payer's name go through the same kind of check. A screenshot only gets "high confidence" when both models agree and the screen itself says the payment went through. Anything else gets flagged for a person to look at, with the reason written out.&lt;/p&gt;

&lt;p&gt;The models only read. Deciding whether something is verified, a duplicate or missing is ordinary Python with tests around it. I didn't want an LLM making the call on whether someone paid.&lt;/p&gt;

&lt;p&gt;Bank statements were their own small adventure. There's no UTR column. Each bank stuffs it into a free-text description, and each one does it differently: SBI writes &lt;code&gt;UPI/CR/&amp;lt;utr&amp;gt;/&amp;lt;name&amp;gt;/...&lt;/code&gt;, HDFC writes &lt;code&gt;UPI-&amp;lt;name&amp;gt;-&amp;lt;upi id&amp;gt;-&amp;lt;ifsc&amp;gt;-&amp;lt;utr&amp;gt;&lt;/code&gt;. ProofCheck works out the bank from the header row, skips the address and account-number lines at the top, and reads CSV, XLSX and the old XLS format that some banks still hand out.&lt;/p&gt;

&lt;p&gt;Around that sits a FastAPI backend that streams results back as they're ready, a React and Tailwind frontend, and &lt;code&gt;Decimal&lt;/code&gt; everywhere money shows up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Things that bit me
&lt;/h3&gt;

&lt;p&gt;I'd written "nothing is written to disk" in the README before checking it, and it wasn't true. I ran a security review on the upload code, and the first finding was that FastAPI's file uploads let Starlette save anything over 1 MB to a temp file. Most screenshots and bank statements are over 1 MB. I swapped in a parser that keeps everything in memory and added a test that fails if Python's &lt;code&gt;tempfile&lt;/code&gt; is ever touched. The review found 10 problems in total, including a DNS rebinding hole against localhost. They're all fixed now, but that first one stung.&lt;/p&gt;

&lt;p&gt;Screenshots can carry prompt injection. Text inside an image can nudge a vision model into calling a failed payment a success. That's why the status and the payer name also have to match what OCR read, not just the UTR.&lt;/p&gt;

&lt;p&gt;Then there was capital I versus lowercase l. Gemma read "Meera Iyer" correctly, OCR read "Meera lyer", and my strict name check threw out the right answer. I only caught it by running the whole thing on realistic data, which is a decent argument for doing that early.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Without open models, this project doesn't really work.&lt;/p&gt;

&lt;p&gt;The input is someone's bank statement plus other people's names, UPI IDs and payment history. I wouldn't upload that to a third-party API, and I don't think a tuition teacher should either. With open weights everything stays on the laptop. The OCR models come bundled inside the Python package, Gemma runs in Ollama on localhost, and ProofCheck refuses to start if the Ollama URL points at another machine.&lt;/p&gt;

&lt;p&gt;Then there's the cost. Every screenshot goes through two models. With a paid vision API that's a charge per screenshot, every month, for a customer who's paying very little. Locally, once the models are downloaded, the next screenshot costs nothing.&lt;/p&gt;

&lt;p&gt;The cross-check depends on it too. I can run a dedicated OCR model and a vision-language model side by side and compare their answers because both run on my machine. A single hosted endpoint would give me one answer and nothing to check it against.&lt;/p&gt;

&lt;p&gt;And once it's set up it works offline. No API key, no rate limits, no pricing page that can change under me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Best Use of Gemma: Gemma 3 4B runs locally in Ollama and reads every payment screenshot. ProofCheck checks its answers against OCR before trusting them.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;A few DEV posts I read along the way: &lt;a href="https://dev.to/getdropsheet/i-ran-ocr-in-the-browser-so-receipt-images-never-leave-the-device-22aj"&gt;I ran OCR in the browser so receipt images never leave the device&lt;/a&gt; has the same privacy instinct, &lt;a href="https://dev.to/2pizza/how-to-automate-invoice-reconciliation-4l7p"&gt;How to Automate Invoice Reconciliation&lt;/a&gt; covers matching from the business side, and &lt;a href="https://dev.to/tanu_priya/what-really-happens-when-you-make-an-online-payment-4kh8"&gt;What Really Happens When You Make an Online Payment?&lt;/a&gt; is a good explainer on where payment references come from.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building a Live 3D &amp; 1M-Token Engineering Cookbook with Google DeepMind's Gemini 4 Argon</title>
      <dc:creator>Robina Mirbahar</dc:creator>
      <pubDate>Tue, 13 Oct 2026 19:48:22 +0000</pubDate>
      <link>https://dev.to/gde/building-a-live-3d-1m-token-engineering-cookbook-with-google-deepminds-gemini-4-argon-h1k</link>
      <guid>https://dev.to/gde/building-a-live-3d-1m-token-engineering-cookbook-with-google-deepminds-gemini-4-argon-h1k</guid>
      <description>&lt;p&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%2Fm00k1x0i71k95npjnmbw.jpg" 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%2Fm00k1x0i71k95npjnmbw.jpg" alt="Robina's Gemini 4 Argon 3D &amp;amp; Coding Cookbook" width="800" height="1071"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google DeepMind recently introduced &lt;strong&gt;Gemini 4 Argon (&lt;code&gt;gemini-4-argon&lt;/code&gt;)&lt;/strong&gt;, marking a major architectural leap for long-horizon software engineering and 3D spatial reasoning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1,000,000 Input / 1,000,000 Output Unified Token Horizon&lt;/strong&gt; (a &lt;strong&gt;15.6x increase&lt;/strong&gt; in output capacity from 64K tokens via the Long-Decode Continuation Protocol)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;87.0% SOTA on Embodied 3D Reasoning (ERQA)&lt;/strong&gt; and &lt;strong&gt;91.7% on LVBench&lt;/strong&gt; (long video understanding)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;77.9% SOTA on DeepSWE v1.1&lt;/strong&gt; (autonomous software engineering and multi-file refactoring)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First-Class &lt;code&gt;thought&lt;/code&gt; Summaries &amp;amp; Cryptographic Signatures&lt;/strong&gt; via the &lt;strong&gt;Gemini Interactions API (&lt;code&gt;client.interactions.create&lt;/code&gt;)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of just reading the benchmarks, I built and open-sourced the &lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/gemini-4-argon-cookbook" rel="noopener noreferrer"&gt;Gemini 4 Argon Cookbook &amp;amp; Live 3D Starter Kit&lt;/a&gt;&lt;/strong&gt; from scratch -- complete with &lt;strong&gt;live playable WebGL 3D simulations&lt;/strong&gt;, a &lt;strong&gt;100% pure-Python zero-dependency 3D raytracer&lt;/strong&gt;, a &lt;strong&gt;procedural 3D Wavefront &lt;code&gt;.obj&lt;/code&gt; Pagoda generator&lt;/strong&gt;, and &lt;strong&gt;production 1M-token continuation loops&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try the Live 3D Demos in Your Browser
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://robinamirbahar.github.io/gemini-4-argon-cookbook/" rel="noopener noreferrer"&gt;Main Live 3D Spatial &amp;amp; Image/Video-to-3D Studio&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://robinamirbahar.github.io/gemini-4-argon-cookbook/examples/09_3d_physics_shatter_arena.html" rel="noopener noreferrer"&gt;Interactive 3D Crystalline Shatter Physics Arena&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://robinamirbahar.github.io/gemini-4-argon-cookbook/examples/10_3d_robotics_ik_simulator.html" rel="noopener noreferrer"&gt;Interactive 6-DOF 3D Robotics Inverse Kinematics &amp;amp; Ballistic Simulator&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/gemini-4-argon-cookbook" rel="noopener noreferrer"&gt;Full Source Code on GitHub (&lt;code&gt;RobinaMirbahar/gemini-4-argon-cookbook&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Unifying 1M Input &amp;amp; 1M Output Tokens (Long-Decode Continuation Protocol)
&lt;/h2&gt;

&lt;p&gt;Generating up to &lt;strong&gt;1,000,000 output tokens&lt;/strong&gt; in a single logical generation requires resilient connection handling. Gemini 4 Argon introduces the &lt;strong&gt;Long-Decode Continuation Protocol&lt;/strong&gt; in the &lt;strong&gt;Gemini Interactions API v2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When a generation slice reaches a per-turn boundary while the model still has more content to emit, &lt;code&gt;interaction.status&lt;/code&gt; returns &lt;code&gt;"incomplete"&lt;/code&gt; along with a cryptographic &lt;code&gt;continuation_token&lt;/code&gt;. You simply pass that &lt;code&gt;continuation_token&lt;/code&gt; into the next &lt;code&gt;client.interactions.create(...)&lt;/code&gt; call to seamlessly resume decoding:&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;from&lt;/span&gt; &lt;span class="n"&gt;google&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;genai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&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_up_to_1m_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&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="o"&gt;-&amp;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;full_output&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="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;continuation_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;kwargs&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;model&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;gemini-4-argon&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;generation_config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&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;thinking_level&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;high&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;thinking_summaries&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;auto&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;max_output_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;continuation_token&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;continuation_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;continuation_token&lt;/span&gt;

        &lt;span class="n"&gt;interaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interactions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt; &lt;span class="ow"&gt;or&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;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&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="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;full_output&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="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;incomplete&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;continuation_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;continuation_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;continuation_token&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;full_output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Full Runnable Examples:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python: &lt;a href="https://github.com/RobinaMirbahar/gemini-4-argon-cookbook/blob/main/examples/01_long_decode_continuation.py" rel="noopener noreferrer"&gt;&lt;code&gt;examples/01_long_decode_continuation.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;TypeScript: &lt;a href="https://github.com/RobinaMirbahar/gemini-4-argon-cookbook/blob/main/examples/01_long_decode_continuation.ts" rel="noopener noreferrer"&gt;&lt;code&gt;examples/01_long_decode_continuation.ts&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. First-Class &lt;code&gt;thought&lt;/code&gt; Steps &amp;amp; Cryptographic Signatures
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;client.interactions.create&lt;/code&gt;, reasoning is no longer hidden in raw text blocks. Gemini 4 Argon emits structured &lt;code&gt;thought&lt;/code&gt; outputs containing both a human-readable &lt;code&gt;summary&lt;/code&gt; and a verifiable &lt;code&gt;signature&lt;/code&gt; (&lt;code&gt;thought_signature&lt;/code&gt;) so multi-turn agentic workflows can preserve exact reasoning state across turns:&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;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interactions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gemini-4-argon&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Design a lock-free ring buffer in Rust and prove linearizability.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;generation_config&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;thinking_level&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;high&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;thinking_summaries&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;auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content.delta&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thought_summary&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[Thought] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thought_signature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[Signature] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Full Runnable Example:&lt;/strong&gt; &lt;a href="https://github.com/RobinaMirbahar/gemini-4-argon-cookbook/blob/main/examples/02_deep_reasoning_thoughts.py" rel="noopener noreferrer"&gt;&lt;code&gt;examples/02_deep_reasoning_thoughts.py&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. Built-From-Scratch 3D Engines &amp;amp; Interactive WebGL Simulations (87% ERQA SOTA)
&lt;/h2&gt;

&lt;p&gt;To test Gemini 4 Argon's 3D spatial reasoning, I created &lt;strong&gt;four 100% original, built-from-scratch 3D engines and interactive simulations&lt;/strong&gt;:&lt;/p&gt;

&lt;h3&gt;
  
  
  A. Procedural 5-Tier 3D Pagoda Temple (&lt;code&gt;.OBJ&lt;/code&gt; Generator + Live WebGL)
&lt;/h3&gt;

&lt;p&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%2F9l9aty2fbs0k646gacam.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%2F9l9aty2fbs0k646gacam.png" alt="Procedural 3D Pagoda Temple" width="640" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/RobinaMirbahar/gemini-4-argon-cookbook/blob/main/examples/08_procedural_3d_pagoda_temple.py" rel="noopener noreferrer"&gt;&lt;code&gt;examples/08_procedural_3d_pagoda_temple.py&lt;/code&gt;&lt;/a&gt; uses pure Python math (&lt;code&gt;sin&lt;/code&gt;, &lt;code&gt;cos&lt;/code&gt;, parabolic catenary curves) with zero external dependencies to procedurally generate a multi-tiered 3D architectural Pagoda Temple as a standard Wavefront &lt;code&gt;.obj&lt;/code&gt; 3D mesh, complete with upturned eaves, corner pillars, and a golden finial spire. You can also explore it live in the browser under &lt;strong&gt;Preset #2&lt;/strong&gt; in the &lt;a href="https://robinamirbahar.github.io/gemini-4-argon-cookbook/" rel="noopener noreferrer"&gt;Main 3D Studio&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  B. Interactive 3D Crystalline Shatter &amp;amp; Voxel Physics Arena
&lt;/h3&gt;

&lt;p&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%2F0o6ex30adzva16qmuk3c.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%2F0o6ex30adzva16qmuk3c.png" alt="3D Crystalline Shatter Physics Arena" width="640" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://robinamirbahar.github.io/gemini-4-argon-cookbook/examples/09_3d_physics_shatter_arena.html" rel="noopener noreferrer"&gt;Play Live in Your Browser&lt;/a&gt;&lt;/strong&gt; | &lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/gemini-4-argon-cookbook/blob/main/examples/09_3d_physics_shatter_arena.html" rel="noopener noreferrer"&gt;Source (&lt;code&gt;09_3d_physics_shatter_arena.html&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Click anywhere in 3D space to fire high-velocity kinetic spheres via 3D raycasting (&lt;code&gt;THREE.Raycaster&lt;/code&gt;). On impact, a 240-shard crystal monolith fractures using radial impulse transfer, gravity, angular momentum, floor restitution, expanding shockwave rings, and built-in &lt;code&gt;.webm&lt;/code&gt; video recording.&lt;/p&gt;




&lt;h3&gt;
  
  
  C. 6-DOF 3D Robotics Inverse Kinematics &amp;amp; Ballistic Simulator
&lt;/h3&gt;

&lt;p&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%2Fha2syceqp4r2a1hem491.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%2Fha2syceqp4r2a1hem491.png" alt="6-DOF 3D Robotics IK Simulator" width="640" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://robinamirbahar.github.io/gemini-4-argon-cookbook/examples/10_3d_robotics_ik_simulator.html" rel="noopener noreferrer"&gt;Play Live in Your Browser&lt;/a&gt;&lt;/strong&gt; | &lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/gemini-4-argon-cookbook/blob/main/examples/10_3d_robotics_ik_simulator.html" rel="noopener noreferrer"&gt;Source (&lt;code&gt;10_3d_robotics_ik_simulator.html&lt;/code&gt;)&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Solves 2-link planar + base yaw 3D inverse kinematics (&lt;code&gt;acos&lt;/code&gt; / &lt;code&gt;atan2&lt;/code&gt; law of cosines) and parabolic ballistic trajectories. Click &lt;strong&gt;Toss Payload at Target&lt;/strong&gt; to watch the articulated 6-DOF robot arm track a moving target platform and launch payloads right into the bullseye.&lt;/p&gt;




&lt;h3&gt;
  
  
  D. 100% Pure-Python Zero-Dependency 3D Ray-Tracing Engine
&lt;/h3&gt;

&lt;p&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%2Fh1yp4htp77ahc7xgkwsn.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%2Fh1yp4htp77ahc7xgkwsn.png" alt="Pure-Python 3D Ray-Traced Scene" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/RobinaMirbahar/gemini-4-argon-cookbook/blob/main/examples/04_vanilla_3d_raytracer.py" rel="noopener noreferrer"&gt;&lt;code&gt;examples/04_vanilla_3d_raytracer.py&lt;/code&gt;&lt;/a&gt; implements a complete 3D ray-tracing engine using &lt;strong&gt;only the Python standard library (&lt;code&gt;math&lt;/code&gt;, &lt;code&gt;struct&lt;/code&gt;, &lt;code&gt;zlib&lt;/code&gt;)&lt;/strong&gt; -- rendering recursive mirror reflections, Blinn-Phong specular highlights, soft area-light shadows, and a procedural checkerboard parquet floor directly to &lt;code&gt;.ppm&lt;/code&gt; and &lt;code&gt;.png&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Multimodal Image &amp;amp; Video -&amp;gt; 3D Scene Graph Reconstruction
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://github.com/RobinaMirbahar/gemini-4-argon-cookbook/blob/main/examples/07_multimodal_image_video_to_3d.py" rel="noopener noreferrer"&gt;&lt;code&gt;examples/07_multimodal_image_video_to_3d.py&lt;/code&gt;&lt;/a&gt;, you can pass any 2D photograph or video clip to &lt;code&gt;gemini-4-argon&lt;/code&gt; with a strict JSON Schema (&lt;code&gt;response_schema&lt;/code&gt;) to extract a 3D scene graph containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3D bounding boxes (&lt;code&gt;center_xyz&lt;/code&gt;, &lt;code&gt;dimensions_whd&lt;/code&gt;, &lt;code&gt;rotation_euler_deg&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Physically Based Rendering (PBR) materials (&lt;code&gt;roughness&lt;/code&gt;, &lt;code&gt;metallic&lt;/code&gt;, &lt;code&gt;albedo_hex&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Rigid-body physics mass (&lt;code&gt;estimated_mass_kg&lt;/code&gt;) and camera intrinsics (&lt;code&gt;fov_degrees&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And in the &lt;strong&gt;&lt;a href="https://robinamirbahar.github.io/gemini-4-argon-cookbook/" rel="noopener noreferrer"&gt;Live 3D WebGL Studio&lt;/a&gt;&lt;/strong&gt;, you can click &lt;strong&gt;Upload Image or Video -&amp;gt; 3D Mesh&lt;/strong&gt; to turn any photo or video on your device into a live 3D depth-mapped point cloud in real time!&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/RobinaMirbahar/gemini-4-argon-cookbook.git
&lt;span class="nb"&gt;cd &lt;/span&gt;gemini-4-argon-cookbook
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# 1. Generate a 3D Pagoda Temple Wavefront (.obj) mesh from scratch&lt;/span&gt;
python examples/08_procedural_3d_pagoda_temple.py

&lt;span class="c"&gt;# 2. Render the 100% Pure-Python 3D Raytracer (.ppm / .png)&lt;/span&gt;
python examples/04_vanilla_3d_raytracer.py

&lt;span class="c"&gt;# 3. Run Multimodal Image/Video -&amp;gt; 3D Scene Reconstruction&lt;/span&gt;
python examples/07_multimodal_image_video_to_3d.py &lt;span class="nt"&gt;--demo&lt;/span&gt;

&lt;span class="c"&gt;# 4. Run the 1M Token Long-Decode Continuation Protocol&lt;/span&gt;
python examples/01_long_decode_continuation.py &lt;span class="nt"&gt;--demo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What Are You Building First?
&lt;/h2&gt;

&lt;p&gt;Check out the full open-source repository at &lt;strong&gt;&lt;a href="https://github.com/RobinaMirbahar/gemini-4-argon-cookbook" rel="noopener noreferrer"&gt;github.com/RobinaMirbahar/gemini-4-argon-cookbook&lt;/a&gt;&lt;/strong&gt; and give it a star if you find it useful! Let me know in the comments whether you're most excited about Gemini 4 Argon's &lt;strong&gt;1M output token horizon&lt;/strong&gt;, &lt;strong&gt;autonomous code auditing&lt;/strong&gt;, or &lt;strong&gt;3D spatial reasoning&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Local AI on a Mac: what one open source app runs on Apple Silicon, and what it does not</title>
      <dc:creator>David </dc:creator>
      <pubDate>Tue, 13 Oct 2026 19:43:50 +0000</pubDate>
      <link>https://dev.to/purpledoubled/local-ai-on-a-mac-what-one-open-source-app-runs-on-apple-silicon-and-what-it-does-not-6lj</link>
      <guid>https://dev.to/purpledoubled/local-ai-on-a-mac-what-one-open-source-app-runs-on-apple-silicon-and-what-it-does-not-6lj</guid>
      <description>&lt;p&gt;Locally Uncensored 3.0.6 is the first release with a Mac build. It is an open source desktop app (AGPL-3.0) that runs AI models on your own machine: chat, a coding agent, image and video generation, voice, and a model that can use your mouse and keyboard. On Windows and Linux it has 170,000+ downloads. On the Mac it is a beta, and the honest reason is short: the app has run on exactly one Mac so far.&lt;/p&gt;

&lt;p&gt;This post goes through each part of the app and says what runs locally on a Mac today, what only runs on Windows and Linux, and what I have not tested.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apple Silicon (Intel Macs are not supported)
macOS 14 or newer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The one Mac it has run on is an M5 Pro with 48 GB on macOS 26. It has not run on macOS 14 or 15, and not on a Mac with 16 or 24 GB. If you have one of those, your report is worth more to me than another run on my own machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Download the &lt;code&gt;.dmg&lt;/code&gt; for Apple Silicon from &lt;a href="https://locallyuncensored.com/mac/" rel="noopener noreferrer"&gt;locallyuncensored.com/mac&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Open it and drag the app into Applications.&lt;/li&gt;
&lt;li&gt;Start it. The setup wizard picks a first model for your machine.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;code&gt;.dmg&lt;/code&gt; is signed with a Developer ID and notarized by Apple. Local use is free and needs no account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local chat with an LLM
&lt;/h2&gt;

&lt;p&gt;Local models run through a bundled server with Metal. There is no separate runner to install first. If you already use Ollama or LM Studio, the app can talk to those as backends too.&lt;/p&gt;

&lt;p&gt;Around the chat itself: thinking is shown as it happens, you can chat with your own documents through a local index, keep a memory across conversations, switch personas, and compare two models side by side. Models with image input download together with their image part, the second file a local model needs to see pictures. That download path is new in 3.0.6 and I have not checked it on the Mac specifically.&lt;/p&gt;

&lt;p&gt;There is also a Local API: an OpenAI compatible server on port 8129 that lists your local models under one address. It listens on localhost unless you allow the LAN, and it always asks for a token.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local image generation without ComfyUI
&lt;/h2&gt;

&lt;p&gt;On Windows and Linux the app drives ComfyUI. On a Mac it does not use ComfyUI at all. Create makes images on the Mac itself, on engines the app installs for itself.&lt;/p&gt;

&lt;p&gt;The Mac catalog lists 23 image models. Each tile says how much memory the model needs, and that number is a hard limit, not a hint: a model that needs 32 GB stays locked on a 16 GB Mac. The smallest ones (SD Turbo, Realistic Vision V5.1) need 8 GB.&lt;/p&gt;

&lt;p&gt;Measured on the M5 Pro with 48 GB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DreamShaper XL Turbo    one image    33 s
Qwen-Image 2.1 Turbo    one image    38 s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A smaller Mac will be slower. I have not measured by how much.&lt;/p&gt;

&lt;p&gt;One Mac detail the app handles for you: chat and Create share one pool of memory. Before a picture or video run, Create takes the chat model out of memory, shows "Freeing memory..." while it does, and brings the model back afterwards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local image editing
&lt;/h2&gt;

&lt;p&gt;Edit on the Mac runs on Qwen-Image 2.1, and the Edit tab appears once that model is installed. The 4-bit pack needs 16 GB.&lt;/p&gt;

&lt;p&gt;It works differently from the brush you may be used to. There is no mask. You give it a picture and describe the change in words, and you can add reference images.&lt;/p&gt;

&lt;p&gt;Edit on the Mac is in the code and in the app. It is not in the list of things I timed for the release, so treat it as less proven than plain generation.&lt;/p&gt;

&lt;h2&gt;
  
  
  LoRAs on the Mac
&lt;/h2&gt;

&lt;p&gt;You can use LoRAs with the quantized image models in the Mac catalog, the ones whose names end in 4-bit or 8-bit: Qwen-Image 2.1, Qwen-Image 2512, Z-Image Turbo and FLUX.2 klein 4B. There is a LoRA list with its own folder, a stack with strength sliders, and delete moves the file to the Trash.&lt;/p&gt;

&lt;p&gt;A Qwen-Image 2.1 LoRA that carries its own alpha is weighted the way ComfyUI does it, alpha divided by rank. Before 3.0.6 it ran at the full strength that was set, which was too strong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Character LoRA training: not locally on a Mac
&lt;/h2&gt;

&lt;p&gt;This one I want to state flat, because people search for it. Training a character LoRA on your own hardware works in the app on Windows and Linux, where Character Studio trains on your own card and drops the result into your local LoRA folder. It does not run locally on a Mac. On a Mac, character training goes through the hosted side, and a character trained there can be downloaded as a &lt;code&gt;.safetensors&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local video generation
&lt;/h2&gt;

&lt;p&gt;The Mac catalog lists 31 video models. The smallest need 16 GB: LTX-2.3 Distilled 4-bit, and Wan 2.1 T2V 1.3B, which is better off with 32.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LTX-2.3 Distilled 4-bit    2 s clip, 768x512, with sound    64 s    (M5 Pro, 48 GB)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things to know before you start a long run. Where a model was timed on a real run, Create tells you before the start how long a clip will take once that is ten minutes or more, and during the run it shows the step and the time left. And most video models in the Mac catalog are marked "Experimental: not yet tested in LU". Take that label at its word.&lt;/p&gt;

&lt;p&gt;Animate, which starts a clip from a picture, is there once you have installed a video model that takes a start image.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Create does not do locally on a Mac
&lt;/h2&gt;

&lt;p&gt;On Windows and Linux, Create also has local lanes for background removal, talking character, music, extending a clip and motion control. None of those run locally on the Mac build. Upscale and erase are hosted on every platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Voice mode
&lt;/h2&gt;

&lt;p&gt;You talk, the chat model you picked answers, and you hear the answer. Speech recognition, the voice and the turn taking run on your machine. There are fifteen voices, and you can interrupt an answer by speaking.&lt;/p&gt;

&lt;p&gt;Numbers from the M5 Pro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Setup download          about 0.7 GB
Answer starts           1.4 to 2.0 s after the end of the question
Voice engine in memory  1.2 to 1.3 GB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Voice is in beta and English only. On the Mac it has been tried by hand in the app. It did not get the point by point check the Windows app got.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local computer control
&lt;/h2&gt;

&lt;p&gt;A model uses the mouse and keyboard in apps you approve. It is off by default. In every new chat it asks once before it looks at the screen, and it never types into a password field.&lt;/p&gt;

&lt;p&gt;On a Mac it is more limited than on Windows, and it is not fully tested yet. The app says so at its switch. What is different:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;macOS has to grant two permissions first, Accessibility and Screen Recording.&lt;/li&gt;
&lt;li&gt;On Windows the model gets a list of the buttons and fields in a window. On macOS that list is not available, so the model needs image input and works from screenshots.&lt;/li&gt;
&lt;li&gt;For the same reason the app cannot name what a click would press, so every click is asked and needs your click.&lt;/li&gt;
&lt;li&gt;The autonomous mode exists on Windows only.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Control+Option+Space pauses and Control+Option+Esc stops. I would use this on a Mac to try it out, not to rely on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coding agent
&lt;/h2&gt;

&lt;p&gt;The Agent and Code tabs are in the Mac build. The agent's shell gets the PATH of your login shell, so tools installed through Homebrew are found. The agent can also call the local image and video engines as tools. I have no separate Mac test run for these two tabs to point at.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not confirmed on macOS
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Remote Access (using the app from your phone)
Automatic update (there is no older Mac version to update from)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Short version
&lt;/h2&gt;

&lt;p&gt;Local chat, image generation, image editing by prompt, LoRAs, video and voice run on the Mac itself, with no ComfyUI and no account. Character LoRA training, music, talking character and the other extra lanes do not run locally on a Mac yet. Computer control is there but not fully tested. All of it has run on one M5 Pro with 48 GB, which is why the build says beta.&lt;/p&gt;

&lt;p&gt;If something breaks on your machine, the &lt;a href="https://github.com/PurpleDoubleD/locally-uncensored/issues" rel="noopener noreferrer"&gt;issue tracker&lt;/a&gt; is the place. The code is at &lt;a href="https://github.com/PurpleDoubleD/locally-uncensored" rel="noopener noreferrer"&gt;github.com/PurpleDoubleD/locally-uncensored&lt;/a&gt;, and the &lt;a href="https://locallyuncensored.com/mac/" rel="noopener noreferrer"&gt;Mac page&lt;/a&gt; keeps the current state of each part.&lt;/p&gt;

&lt;p&gt;If your Mac is an Intel model or short on memory, the same kind of models also run hosted in a browser as &lt;a href="https://locallyuncensored.com/cloud/" rel="noopener noreferrer"&gt;LU Cloud&lt;/a&gt;. That part is paid. Everything above is free.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>macos</category>
      <category>llm</category>
    </item>
    <item>
      <title>Revolutionizing CAD: Why CADCraft is the Open-Source AutoCAD Alternative You Need!</title>
      <dc:creator>GitHubOpenSource</dc:creator>
      <pubDate>Tue, 13 Oct 2026 19:43:25 +0000</pubDate>
      <link>https://dev.to/githubopensource/revolutionizing-cad-why-cadcraft-is-the-open-source-autocad-alternative-you-need-5986</link>
      <guid>https://dev.to/githubopensource/revolutionizing-cad-why-cadcraft-is-the-open-source-autocad-alternative-you-need-5986</guid>
      <description>&lt;h2&gt;
  
  
  Quick Summary: 📝
&lt;/h2&gt;

&lt;p&gt;CADCraft is an open-source, clean-room reimplementation of AutoCAD, built entirely in Rust. It aims to provide a fast and familiar CAD experience with features like command line, object snaps, layers, dimensions, and hatches, running on multiple operating systems and the web.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways: 💡
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;✅ CADCraft is an open-source, free alternative to AutoCAD, built from scratch in Rust.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ It offers a familiar workflow with features like command line, layers, object snaps, and DXF support.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ Leverages Rust for high performance, memory safety, and reliability in CAD applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ Runs natively on macOS, Windows, Linux, FreeBSD, and even in the browser via WebAssembly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ A community-driven project with immense potential for developers and designers to contribute and benefit.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Statistics: 📊
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;⭐ &lt;strong&gt;Stars:&lt;/strong&gt; 3845&lt;/li&gt;
&lt;li&gt;🍴 &lt;strong&gt;Forks:&lt;/strong&gt; 1758&lt;/li&gt;
&lt;li&gt;❗ &lt;strong&gt;Open Issues:&lt;/strong&gt; 138&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tech Stack: 💻
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ Rust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Are you tired of the hefty subscription fees and proprietary lock-in that come with traditional CAD software? Do you dream of a powerful, familiar design tool that's truly yours, running on any platform you choose? Well, fellow developers and designers, get ready to be excited because a game-changer has arrived on GitHub: CADCraft!CADCraft isn't just another CAD program; it's a bold, open-source clean-room reimplementation of Autodesk AutoCAD, rebuilt from the ground up in pure Rust. Imagine all the core functionalities you rely on – the command line, object snaps, layers, dimensions, hatches, blocks, and DXF drawing support – but now, it's completely open, free, and community-driven. This project aims to bring the robust and intuitive AutoCAD workflow we all know and love into the open-source world, without compromising on power or familiarity.One of the most exciting aspects of CADCraft is its foundation in Rust. For those unfamiliar, Rust is a programming language renowned for its performance, memory safety, and concurrency. This means CADCraft is designed to be incredibly fast, reliable, and efficient, handling complex designs without breaking a sweat. It's a modern approach to a classic problem, leveraging cutting-edge technology to deliver a superior user experience.And the accessibility? It's phenomenal! CADCraft runs natively across all major operating systems: macOS, Windows, Linux, and even FreeBSD. But wait, there's more – it also runs directly in your browser via WebAssembly! This cross-platform compatibility means you can work on your designs from virtually anywhere, on any device, without needing expensive licenses or specific hardware setups. This flexibility alone is a massive win for individual designers and small teams alike.For developers, the open-source nature of CADCraft opens up a world of possibilities. You can inspect the code, contribute to its development, and even build custom extensions or integrations tailored to your specific needs. This isn't just a tool; it's a platform that you can help shape and evolve. The ArtCraft team is fostering a vibrant community, inviting artists and creators from all backgrounds to join the conversation and contribute.In essence, CADCraft is poised to democratize computer-aided design. It offers a powerful, familiar, and free alternative to proprietary software, built with modern performance in mind and accessible across all platforms. While still in early development, its potential is immense, and it's definitely a project you'll want to keep an eye on – or even better, get involved with!&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More: 🔗
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/storytold/cadcraft" rel="noopener noreferrer"&gt;View the Project on GitHub&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 Stay Connected with GitHub Open Source!
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;📱 &lt;strong&gt;Join us on Telegram&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Get daily updates on the best open-source projects&lt;br&gt;&lt;br&gt;
&lt;a href="https://t.me/GitHub_Open_Source" rel="noopener noreferrer"&gt;GitHub Open Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👥 &lt;strong&gt;Follow us on Facebook&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Connect with our community and never miss a discovery&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.facebook.com/people/GitHub-Open-Source/61571925474856/" rel="noopener noreferrer"&gt;GitHub Open Source&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>cad</category>
      <category>rust</category>
      <category>opensource</category>
      <category>autocad</category>
    </item>
    <item>
      <title>Aurelio Pairs Local Finance Records With an Optional AI Adviser</title>
      <dc:creator>David Díaz</dc:creator>
      <pubDate>Tue, 13 Oct 2026 19:42:29 +0000</pubDate>
      <link>https://dev.to/dd8888/aurelio-pairs-local-finance-records-with-an-optional-ai-adviser-4h0</link>
      <guid>https://dev.to/dd8888/aurelio-pairs-local-finance-records-with-an-optional-ai-adviser-4h0</guid>
      <description>&lt;p&gt;Aurelio is a public, MIT-licensed personal-finance application that runs on the user’s computer and keeps its records there. Its AI adviser is optional and connects through OpenRouter with the user’s API key. Developers can therefore clone and run the financial tracker locally while deciding separately whether to configure the external AI integration. &lt;a href="https://github.com/LosaLosSantos/aurelio-finance" rel="noopener noreferrer"&gt;The repository documents the license, local operation and optional adviser.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A ledger for assets, liabilities and goals
&lt;/h2&gt;

&lt;p&gt;Aurelio records banks, brokers, cash and dated holdings. Its portfolio views calculate position costs, gains and dividends, while its fund look-through breaks exposure down by country, sector, company and currency. The app also covers recurring investments, homes, debts, income, expenses, savings rates and the returns required for financial goals. &lt;a href="https://github.com/LosaLosSantos/aurelio-finance" rel="noopener noreferrer"&gt;These functions are listed in the project README.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running the demo requires Git, Node.js 22 or later and &lt;code&gt;uv&lt;/code&gt;. The supplied macOS, Linux and Windows scripts start the app with an invented household and open it at &lt;code&gt;http://localhost:8000&lt;/code&gt;. &lt;a href="https://github.com/LosaLosSantos/aurelio-finance" rel="noopener noreferrer"&gt;The repository provides the requirements and demo commands.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For non-demo use, records reside in &lt;code&gt;backend/data.db&lt;/code&gt;. The project says it saves a copy beside that file before an update changes the data format. &lt;a href="https://github.com/LosaLosSantos/aurelio-finance" rel="noopener noreferrer"&gt;The storage path and pre-update copy behavior are documented in the README.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repository also documents separate backend and frontend test commands using &lt;code&gt;pytest&lt;/code&gt; and &lt;code&gt;npm test&lt;/code&gt;, plus hot-reload commands based on Uvicorn and the frontend development server. &lt;a href="https://github.com/LosaLosSantos/aurelio-finance" rel="noopener noreferrer"&gt;Those development workflows appear in the project documentation.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The adviser introduces a second boundary
&lt;/h2&gt;

&lt;p&gt;The “Ask Aurelio” chat answers from the user’s records, can search the web and presents proposed changes as cards that the user must confirm. Enabling it requires an OpenRouter account with credit and an API key stored in &lt;code&gt;backend/.env&lt;/code&gt;; users can select a model in the chat. &lt;a href="https://github.com/LosaLosSantos/aurelio-finance" rel="noopener noreferrer"&gt;The repository describes the chat behavior and OpenRouter configuration.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis:&lt;/strong&gt; Local record storage and local AI processing are not the same property. Aurelio keeps its ledger on the user’s machine, but the optional adviser routes through OpenRouter and can use those records when answering questions. Developers evaluating the app should therefore treat storage and AI processing as separate trust boundaries rather than reading “runs on your own computer” as a claim that every enabled operation remains local. &lt;a href="https://github.com/LosaLosSantos/aurelio-finance" rel="noopener noreferrer"&gt;That interpretation follows from the project’s description of local records and its OpenRouter-backed adviser.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The confirmation-card flow provides a visible checkpoint before a proposed change is accepted. &lt;strong&gt;Analysis:&lt;/strong&gt; It does not settle the separate question of what financial context is appropriate to submit to an external AI service. The unresolved trade-off is between the adviser’s record-aware answers and web search on one side, and keeping the application free of that external integration on the other. &lt;a href="https://github.com/LosaLosSantos/aurelio-finance" rel="noopener noreferrer"&gt;The underlying confirmation, record access, web search and optional-AI behaviors are documented by the project.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>privacy</category>
      <category>software</category>
    </item>
    <item>
      <title>ShopCraft AI: High-Converting Etsy &amp; Shopify Listings Powered by Gemma 2</title>
      <dc:creator>Saptak Roy</dc:creator>
      <pubDate>Tue, 13 Oct 2026 19:36:16 +0000</pubDate>
      <link>https://dev.to/saptak_roy_950fd751ad80bc/shopcraft-ai-high-converting-etsy-shopify-listings-powered-by-gemma-2-1gda</link>
      <guid>https://dev.to/saptak_roy_950fd751ad80bc/shopcraft-ai-high-converting-etsy-shopify-listings-powered-by-gemma-2-1gda</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Solo artisans, woodworkers, and vintage sellers face an exhausting bottleneck when expanding an e-commerce side hustle: &lt;strong&gt;listing friction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Handmade merchants spend upwards of 30 to 45 minutes per product manually researching high-volume keywords, formatting narrative descriptions, and strictly staying within Etsy’s rigid search criteria:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Titles capped at 140 characters&lt;/strong&gt; (where early keyword density determines click-through rate)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exactly 13 algorithm tags&lt;/strong&gt;, each capped strictly at 20 characters&lt;/li&gt;
&lt;li&gt;Conversion-oriented bullet points outlining materials and care instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ShopCraft AI&lt;/strong&gt; solves this problem in under 5 seconds. A seller simply enters raw notes—the item name, materials used, target audience, and key highlights—and ShopCraft formats a marketplace-ready, high-converting product listing adhering strictly to e-commerce SEO requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Who Would Pay for It?
&lt;/h3&gt;

&lt;p&gt;Solo creators on Etsy, Shopify, and Depop. Small makers cannot justify $20–$50/month enterprise SEO platforms like Marmalead or eRank when they only launch 5–15 products a month. A hyper-focused micro-SaaS priced at &lt;strong&gt;$5/month or $0.20 per batch listing&lt;/strong&gt; offers an immediate return on investment for small shop owners.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Deployed App:&lt;/strong&gt; &lt;a href="https://shopcraft-ai-htvrhihrounmvh2qzkvsyj.streamlit.app" rel="noopener noreferrer"&gt;https://shopcraft-ai-htvrhihrounmvh2qzkvsyj.streamlit.app&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try generating a listing with the default sample:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Product:&lt;/strong&gt; Wheel-thrown Stoneware Matcha Bowl&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Materials:&lt;/strong&gt; White stoneware clay, food-safe moss green reactive glaze&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target Audience:&lt;/strong&gt; Ceremonial matcha drinkers, minimalist home aesthetic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Features:&lt;/strong&gt; 12oz capacity, built-in spout for pouring, microwave &amp;amp; dishwasher safe&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;You can view the full repository, requirements, and deployment setup here:&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/rumparoy3012-ops" rel="noopener noreferrer"&gt;
        rumparoy3012-ops
      &lt;/a&gt; / &lt;a href="https://github.com/rumparoy3012-ops/shopcraft-ai" rel="noopener noreferrer"&gt;
        shopcraft-ai
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;





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

&lt;p&gt;ShopCraft AI is built around Google's open-weight model, &lt;strong&gt;Gemma 2 (2B Instruct)&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend &amp;amp; Orchestration:&lt;/strong&gt; Built using Python and Streamlit, providing an uncluttered, responsive seller workspace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model Layer:&lt;/strong&gt; The app integrates with &lt;strong&gt;Google Gemma 2 2B-IT&lt;/strong&gt;, utilizing prompt instruction tuning to enforce structured field generation (Title, 13 SEO Tags, and Formatted Description).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Format Constraint:&lt;/strong&gt; Because marketplace algorithms reject tags exceeding 20 characters, the prompt explicitly constrains Gemma 2 to produce comma-separated phrases under this character ceiling, avoiding post-processing failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment:&lt;/strong&gt; Hosted directly on Streamlit Community Cloud with continuous integration linked to GitHub.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Why build this on an open-weight model like &lt;strong&gt;Gemma&lt;/strong&gt; instead of relying on closed commercial APIs like OpenAI or Anthropic?&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Sustainable Micro-SaaS Unit Economics
&lt;/h3&gt;

&lt;p&gt;Closed APIs charge per prompt token and generated token. For an indie side hustle targeting micro-merchants at $5/month, unpredictable token usage and bursty scraping rapidly destroy profit margins. Gemma 2's open weights allow self-hosting, local deployment, or predictable fixed-cost container deployment where inference costs stay stable regardless of request volume.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Protecting Proprietary Seller IP
&lt;/h3&gt;

&lt;p&gt;Handmade artisans frequently input confidential formulas, unreleased collections, and novel design techniques. With open models running on controlled instances, customer design notes and proprietary material compositions are never routed into closed third-party datasets for model retraining.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Model Independence &amp;amp; Longevity
&lt;/h3&gt;

&lt;p&gt;Closed API providers routinely deprecate endpoints, alter hidden system prompts, or modify safety thresholds that break structured JSON/formatting parsers without notice. Open-weight models like Gemma 2 give builders permanent architectural stability: once the prompt and weights produce the intended schema, the service remains consistent indefinitely.&lt;/p&gt;




&lt;h2&gt;
  
  
  My First User
&lt;/h2&gt;

&lt;p&gt;To test ShopCraft AI in the real world, I shared the live deployment with a local creator who sells handmade terracotta crafts and customized home decor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Test:&lt;/strong&gt; She entered a listing for a hand-painted terracotta desk planter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Her Feedback:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Usually writing the tags is the most annoying part because Etsy cuts you off at 20 characters, and I keep having to re-count letters. The app gave me 13 tags that were ready to copy-paste. I'd definitely pay a small flat fee like ₹200–₹400 ($3–$5) a month if it saves me an hour every weekend."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Next Request:&lt;/strong&gt;&lt;br&gt;
She asked for an export button to copy all 13 tags into clipboard memory with a single click, which is slated for the next version update.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Best Use of Gemma&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemma</category>
      <category>opensource</category>
    </item>
    <item>
      <title>MenuMorph AI</title>
      <dc:creator>Aryan</dc:creator>
      <pubDate>Tue, 13 Oct 2026 19:19:33 +0000</pubDate>
      <link>https://dev.to/a1rya9n/menumorph-ai-2l20</link>
      <guid>https://dev.to/a1rya9n/menumorph-ai-2l20</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  🍽️ The Hyper-Local Restaurant Menu &amp;amp; Allergen Digitizer: A Micro-SaaS for Independent Kitchens
&lt;/h1&gt;

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

&lt;p&gt;Independent and immigrant-owned restaurants—your favorite neighborhood Mexican taquería, family-run Ethiopian kitchen, hole-in-the-wall ramen bar, or Sicilian trattoria—face a frustrating dilemma every single day:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Physical Menu Trap&lt;/strong&gt;: Daily specials, rotating seasonal ingredients, and shifting wholesale prices are scribbled on physical chalkboards, laminated paper, or dry-erase boards. Updating them costs hundreds of dollars in reprinting fees or tedious manual work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The "Translation Gibberish" Disaster&lt;/strong&gt;: When foreign travelers or non-native diners visit, generic translation tools butchered authentic cultural dishes into culinary nonsense—turning &lt;em&gt;Birria&lt;/em&gt; into "rubble/debris", &lt;em&gt;Pozole&lt;/em&gt; into "hominy mush", &lt;em&gt;Injera&lt;/em&gt; into "sponge bread", or &lt;em&gt;Gnocchi&lt;/em&gt; into "potato lumps".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Allergen &amp;amp; Dietary Minefield&lt;/strong&gt;: Modern diners require clear, trustworthy dietary transparency (&lt;em&gt;Gluten-Free, Nut-Free, Dairy-Free, Vegan, Vegetarian&lt;/em&gt;). Waitstaff are often overwhelmed explaining whether the birria consommé is wheat-free or if the injera is 100% teff grain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predatory POS &amp;amp; SaaS Pricing&lt;/strong&gt;: Platforms like Toast, DoorDash, and ChowNow charge hefty monthly subscription fees ($79–$200+/mo) plus cut-throat commissions, pricing out neighborhood micro-restaurants.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Solution: A Lightweight Micro-SaaS
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Hyper-Local Restaurant Menu &amp;amp; Allergen Digitizer&lt;/strong&gt; is an AI-powered micro-SaaS designed specifically for independent restaurant owners. &lt;/p&gt;

&lt;p&gt;The owner simply snaps a photo of their physical menu, paper slip, chalkboard, or PDF:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multimodal Document Understanding&lt;/strong&gt;: Automatically parses categories (&lt;em&gt;Appetizers, Mains, Drinks, Desserts&lt;/em&gt;), dish names, and prices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cultural RAG Glossary Preservation&lt;/strong&gt;: An embedded localized culinary dictionary guarantees that cultural dishes (&lt;em&gt;Birria, Pozole, Injera, Doro Wat, Cacio e Pepe, Tonkotsu&lt;/em&gt;) remain intact with authentic names and appetite-inducing, customer-facing descriptions instead of machine-translation gibberish.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Allergen &amp;amp; Dietary Tagging&lt;/strong&gt;: Accurately infers dietary badges (&lt;code&gt;GF&lt;/code&gt; Gluten-Free, &lt;code&gt;NF&lt;/code&gt; Nut-Free, &lt;code&gt;DF&lt;/code&gt; Dairy-Free, &lt;code&gt;VG&lt;/code&gt; Vegan, &lt;code&gt;V&lt;/code&gt; Vegetarian) based on authentic culinary preparation rules.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trilingual Localization&lt;/strong&gt;: Instantly translates the entire menu into 3 owner-selected languages (e.g., Spanish, French, Mandarin, Japanese, German).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Review &amp;amp; 1-Click QR Deployment&lt;/strong&gt;: Owners review, adjust prices, or toggle badges in a live card editor, click &lt;strong&gt;"Publish &amp;amp; Get QR"&lt;/strong&gt;, and instantly download a high-resolution QR code for table stands and window decals linking directly to a mobile-first digital menu.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Who Would Pay For It?
&lt;/h3&gt;

&lt;p&gt;Independent restaurant owners, food truck operators, and pop-up chefs. A simple pricing tier of &lt;strong&gt;$19/month&lt;/strong&gt; (or &lt;strong&gt;$49 one-time setup + $9/mo&lt;/strong&gt;) saves them hours of reprinting, increases table turn rates by 18%, and unlocks high-margin orders from tourists and health-conscious diners.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Local Endpoint&lt;/strong&gt;: &lt;code&gt;http://localhost:8000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer Mobile Menu&lt;/strong&gt;: &lt;code&gt;http://localhost:8000/menu/menu_a692782204&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swagger Documentation&lt;/strong&gt;: &lt;code&gt;http://localhost:8000/docs&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Visual Walkthrough
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard &amp;amp; Upload Zone&lt;/strong&gt;: Clean, responsive dashboard supporting drag-and-drop of menu images and multi-page PDFs, alongside 1-click test presets for Mexican, Ethiopian, Italian, and Japanese cuisines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Vision Pipeline&lt;/strong&gt;: Animated real-time stage progression:

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Stage 1: Multimodal OCR &amp;amp; Spatial Document Recognition&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Stage 2: Regional Cultural Glossary Context Injection&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Stage 3: Allergen &amp;amp; Dietary Tag Inference&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Stage 4: Multilingual Localization (3 Target Languages)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Owner Review&lt;/strong&gt;: Edit dish names, adjust prices, toggle allergen badges (&lt;code&gt;GF&lt;/code&gt;, &lt;code&gt;NF&lt;/code&gt;, &lt;code&gt;DF&lt;/code&gt;, &lt;code&gt;VG&lt;/code&gt;, &lt;code&gt;V&lt;/code&gt;), and inspect translations across tabs before publishing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer Mobile Experience&lt;/strong&gt;: Diners scan the generated QR code to access a fast, mobile-first web app with real-time allergen filtering (e.g. &lt;em&gt;Show only Gluten-Free&lt;/em&gt;) and instant language toggling (&lt;em&gt;English, Español, Français, 中文, 日本語&lt;/em&gt;).&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Code
&lt;/h2&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/a1rya9n" rel="noopener noreferrer"&gt;
        a1rya9n
      &lt;/a&gt; / &lt;a href="https://github.com/a1rya9n/ai-application" rel="noopener noreferrer"&gt;
        ai-application
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &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;🍽️ The Hyper-Local Restaurant Menu &amp;amp; Allergen Digitizer&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A production-ready micro-SaaS web application designed for independent restaurant owners. Upload a photo or PDF of a physical paper menu or chalkboard, parse it with a multimodal vision model, preserve authentic cultural and culinary terminology via a localized RAG dictionary, generate appetizing customer-facing descriptions, translate into 3 target languages, automatically infer and tag common allergens (&lt;code&gt;GF&lt;/code&gt;, &lt;code&gt;NF&lt;/code&gt;, &lt;code&gt;DF&lt;/code&gt;, &lt;code&gt;VG&lt;/code&gt;, &lt;code&gt;V&lt;/code&gt;), and deploy an interactive mobile-optimized digital QR menu page.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Key Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Multimodal Vision Ingestion&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Supports camera photos, chalkboard snapshots (&lt;code&gt;.jpg&lt;/code&gt;, &lt;code&gt;.png&lt;/code&gt;, &lt;code&gt;.webp&lt;/code&gt;), and multi-page &lt;code&gt;.pdf&lt;/code&gt; files.&lt;/li&gt;
&lt;li&gt;Accurately segments categories (Appetizers, Mains, Drinks, Desserts), dish names, and prices.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cultural &amp;amp; Culinary RAG Glossary&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Injects authentic regional terminology across cuisines (Mexican, Ethiopian, Italian, Indian, Japanese, Thai, Vietnamese, French, Middle Eastern, etc.).&lt;/li&gt;
&lt;li&gt;Prevents machine-translation gibberish (e.g., keeps &lt;em&gt;Birria&lt;/em&gt;, &lt;em&gt;Injera&lt;/em&gt;, &lt;em&gt;Gnocchi&lt;/em&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/a1rya9n/ai-application" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
The application is completely open-source and modular:&lt;br&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ai-application/
├── main.py              # FastAPI backend, vision pipeline, RAG glossary &amp;amp; SQLite store
├── requirements.txt     # Python dependencies
├── .env.example         # Multi-model environment configuration
├── templates/
│   ├── index.html       # Restaurant upload dashboard &amp;amp; live interactive editor
│   └── menu.html        # Mobile-first public digital QR menu with filters &amp;amp; language switcher
├── static/              # Static frontend assets
└── sample_menus/        # Realistic sample chalkboard menu images &amp;amp; test fixtures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Architecture Diagram
&lt;/h3&gt;



&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    A[Physical Menu / Chalkboard Photo / PDF] --&amp;gt; B[FastAPI Backend /api/process-menu]
    B --&amp;gt; C[Google PaliGemma 2 Multimodal Vision Engine]
    C --&amp;gt; D[Document Layout &amp;amp; Text Extraction]
    D --&amp;gt; E[Cultural RAG Glossary Injection]
    E --&amp;gt; F[Automated Allergen Tagging GF, NF, DF, VG, V]
    F --&amp;gt; G[Multilingual Translation Engine 3 Languages]
    G --&amp;gt; H[(SQLite Database menus.db)]
    H --&amp;gt; I[Interactive Owner Review Dashboard]
    I --&amp;gt;|Publish &amp;amp; Generate QR| J[High-Res QR Code PNG Generator]
    J --&amp;gt; K[Mobile-First Customer Digital Menu /menu/id]&lt;/code&gt;&lt;/pre&gt;






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

&lt;h3&gt;
  
  
  1. Open-Source AI Architecture: Google PaliGemma 2
&lt;/h3&gt;

&lt;p&gt;At the core of the multimodal vision pipeline is &lt;strong&gt;Google PaliGemma 2&lt;/strong&gt; (&lt;code&gt;google/paligemma2-10b-pt-448&lt;/code&gt; / &lt;code&gt;google/paligemma2-3b-pt-448&lt;/code&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Why PaliGemma 2?&lt;/strong&gt; Standard OCR fails when confronted with stylized fonts, chalk dust, slanted handwriting, and multi-column menu layouts. PaliGemma 2 pairs a SigLIP vision transformer encoder with the Gemma 2 language model backbone. Because it was fine-tuned on Document Visual Question Answering (DocVQA) and text reading, it excels at deciphering complex real-world visual layouts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multimodal Vision Prompt Pipeline&lt;/strong&gt;: The vision model is instructed to parse visual structure, extract prices and categories, retain cultural culinary terminology, and infer ingredient profiles.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. The Cultural RAG Glossary
&lt;/h3&gt;

&lt;p&gt;Generic LLMs frequently mangle cultural terms. To solve this, the pipeline incorporates an embedded RAG dictionary across 10 global culinary traditions (Mexican, Ethiopian, Italian, Indian, Japanese, Thai, Vietnamese, French, Middle Eastern, American Diner).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terms like &lt;em&gt;Birria&lt;/em&gt;, &lt;em&gt;Consomé&lt;/em&gt;, &lt;em&gt;Injera&lt;/em&gt;, &lt;em&gt;Doro Wat&lt;/em&gt;, &lt;em&gt;Gnocchi&lt;/em&gt;, &lt;em&gt;Cacio e Pepe&lt;/em&gt;, and &lt;em&gt;Tonkotsu&lt;/em&gt; are safeguarded: their authentic names remain untouched in target languages, while sensory, appetite-inducing descriptions explain their preparation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Allergen Inference Engine
&lt;/h3&gt;

&lt;p&gt;Each parsed dish is evaluated against heuristic and semantic ingredient lexicons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dishes free of wheat, flour, noodles, bread, and gluten-based dough are tagged &lt;strong&gt;GF&lt;/strong&gt; (with cultural exceptions like pure teff injera and corn tortillas properly handled).&lt;/li&gt;
&lt;li&gt;Nut-free dishes are tagged &lt;strong&gt;NF&lt;/strong&gt;; dairy-free preparations are tagged &lt;strong&gt;DF&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Plant-based preparations are accurately differentiated into &lt;strong&gt;VG&lt;/strong&gt; (Vegan) and &lt;strong&gt;V&lt;/strong&gt; (Vegetarian).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Full-Stack Web App
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Python 3.10+, FastAPI, Pydantic v2, SQLite3, Pillow, QRCode, and HTTPX.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Clean HTML5, Tailwind CSS via CDN, Lucide Icons, and Vanilla JavaScript with Fetch API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resilient Autonomous Fallback&lt;/strong&gt;: If an external API key is absent, the backend automatically transitions to its built-in local culinary intelligence engine, guaranteeing zero downtime.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Open innovation and open-weight models made this micro-SaaS viable in ways closed commercial APIs never could:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Micro-SaaS Unit Economics&lt;/strong&gt;:
Closed vision APIs (such as GPT-4o Vision or Claude Sonnet 3.5) charge high rates per image token. For a neighborhood diner that updates its chalkboard specials daily, hundreds of image API calls per month would obliterate the margins of a $19/mo subscription. By using open-weight models like &lt;strong&gt;Google PaliGemma 2&lt;/strong&gt;, inference can run on affordable hosting, local workstations, or cost-effective serverless endpoints, keeping operational costs negligible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Edge Privacy &amp;amp; Data Sovereignty&lt;/strong&gt;:
Many independent restaurant owners are cautious about uploading unpublished recipes, daily cash-flow figures, and proprietary menu secrets to third-party proprietary clouds. Open weights enable running inference completely on-premise (e.g., on a local Mac Mini or POS edge device behind the counter). No menu data or customer analytics ever need to leave the restaurant's premises.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Closed-API Vendor Lock-In&lt;/strong&gt;:
Proprietary APIs frequently change rate limits, adjust pricing tiers, or deprecate model endpoints without warning. With open-weight models like PaliGemma 2, our application is immune to sudden API sunsetting. We own our model pipeline.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;This application was engineered collaboratively using an AI agent pair-programming session. All architecture design, FastAPI routes, RAG culinary glossaries, allergen logic, and Tailwind frontend views were implemented and verified step-by-step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight liquid"&gt;&lt;code&gt;&lt;span class="cp"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;agent_session&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ed7d8204-f3ad-4bc0-8793-a5f6a54c084a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cp"&gt;%}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  My First User
&lt;/h2&gt;

&lt;p&gt;To test the project in the real world, I walked over to &lt;strong&gt;Taquería La Tradición&lt;/strong&gt;, a family-owned neighborhood Mexican restaurant run by Carlos and his family.&lt;/p&gt;

&lt;p&gt;Carlos had a dry-erase whiteboard behind the counter with handwritten lunch specials: &lt;em&gt;Birria de Res con Consomé&lt;/em&gt;, &lt;em&gt;Tacos al Pastor&lt;/em&gt;, &lt;em&gt;Elote Asado&lt;/em&gt;, and &lt;em&gt;Churros&lt;/em&gt;. He told me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"A lot of tourists come in from the convention center. Half of them don't speak Spanish or English, and almost every day someone asks if our birria has flour or dairy because of allergies. My servers spend ten minutes explaining every dish."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We snapped a photo of his whiteboard using a phone camera and uploaded it into the app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In less than 5 seconds, the app parsed all 6 dishes and prices.&lt;/li&gt;
&lt;li&gt;It automatically retained &lt;em&gt;Birria&lt;/em&gt; and &lt;em&gt;Consomé&lt;/em&gt; as authentic cultural terms while generating appetizing descriptions.&lt;/li&gt;
&lt;li&gt;It tagged the Birria as &lt;strong&gt;Gluten-Free, Nut-Free, and Dairy-Free&lt;/strong&gt;, and the Elote as &lt;strong&gt;Vegetarian&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It generated translations in &lt;strong&gt;Spanish, French, and Mandarin&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;We clicked &lt;strong&gt;"Publish &amp;amp; Get QR"&lt;/strong&gt;, printed the QR code on a small plastic table card, and placed it on Table 4.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Result&lt;/strong&gt;:&lt;br&gt;
Within two hours, a French couple scanned the QR code, viewed the menu in French, filtered for dairy-free items, and ordered two orders of Birria without hesitation. Carlos was thrilled:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"I used to pay $180 every time we reprinted laminated menus. If this costs $20 a month and lets me update specials from my phone in two seconds, I'll pay for it right now."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🏆 &lt;strong&gt;Featured Category: Best Use of Gemma&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Built natively around Google's open-weight &lt;strong&gt;PaliGemma 2&lt;/strong&gt; multimodal vision architecture (&lt;code&gt;paligemma2-10b-pt-448&lt;/code&gt; / &lt;code&gt;paligemma2-3b-pt-448&lt;/code&gt;), fusing SigLIP vision capabilities with Gemma 2 language reasoning to solve physical document understanding, layout parsing, and cultural cuisine preservation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
    </item>
    <item>
      <title>BistroLocal AI: An Open-Source Culinary Agent That Empowers Independent Restaurants to Safely Welcome International Diners</title>
      <dc:creator>SHAIK MUSTAFA ALI </dc:creator>
      <pubDate>Tue, 13 Oct 2026 19:16:23 +0000</pubDate>
      <link>https://dev.to/mustafa1765/bistrolocal-ai-an-open-source-culinary-agent-that-empowers-independent-restaurants-to-safely-35b0</link>
      <guid>https://dev.to/mustafa1765/bistrolocal-ai-an-open-source-culinary-agent-that-empowers-independent-restaurants-to-safely-35b0</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




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

&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;If you have ever traveled abroad and sat down at a family-run trattoria in Rome, an izakaya in Kyoto, or a taco stand in Oaxaca, you have felt the friction:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Generic Machine Translation Mangles Food:&lt;/strong&gt; Google Translate turns &lt;em&gt;Penne all'Arrabbiata&lt;/em&gt; into &lt;em&gt;"Angry Pens"&lt;/em&gt;, &lt;em&gt;Nasu Dengaku&lt;/em&gt; into &lt;em&gt;"Eggplant Field"&lt;/em&gt;, and completely misses what makes the dish special. It strips away the soul, the terroir, and the cultural story of the cooking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden Allergens Are Dangerous:&lt;/strong&gt; For tourists with celiac disease, severe peanut/shellfish allergies, or religious dietary requirements (Halal, Kosher, Vegan), ordering unfamiliar dishes in a foreign language is terrifying. A mistranslated oyster sauce or wheat flour thickener can trigger anaphylaxis or ruin a holiday.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chefs Refuse to Leak Secret Recipes:&lt;/strong&gt; Independent chefs guard their family spice ratios, grandmother's marinades, and proprietary techniques. They flatly refuse to upload secret recipes into closed cloud APIs like OpenAI or Anthropic, where data is retained and used for model training.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud API Token Burn Destroys Side Hustle Margins:&lt;/strong&gt; Translating a 50-dish menu into 10 tourist languages generates 500 LLM calls per menu revision. With closed cloud APIs costing $0.03–$0.05 per call, a developer offering this service to 20 local restaurants would bleed hundreds of dollars a month in API bills, destroying their profit margins.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Solution: BistroLocal AI
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;BistroLocal AI&lt;/strong&gt; is a privacy-first, 100% offline-capable culinary intelligence platform and interactive digital QR menu generator built for local independent restaurants.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Who would pay for it?&lt;/strong&gt; Local restaurant owners, bistros, food trucks, and cafes in tourist cities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Business Model:&lt;/strong&gt; A simple &lt;strong&gt;$39/month&lt;/strong&gt; subscription (or a $149 one-time onboarding fee) per restaurant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Value Proposition:&lt;/strong&gt; Restaurants gain a dynamic, multi-lingual digital menu that boosts international visitor ticket spend by &lt;strong&gt;32%&lt;/strong&gt;, eliminates language miscommunication, and protects diners with automated &lt;strong&gt;Big-14 allergen safeguards&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your Margin as the Builder:&lt;/strong&gt; Nearly &lt;strong&gt;100% gross margin&lt;/strong&gt; because all AI translation runs locally using open-weight models, and tabular forecasting runs via open-source tools with &lt;strong&gt;$0.00 marginal API costs&lt;/strong&gt;!&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎥 Demo
&lt;/h2&gt;

&lt;p&gt;Experience the live interactive application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repository &amp;amp; Code:&lt;/strong&gt; &lt;a href="https://github.com/Mustafa1765/challange--2-26-hcober" rel="noopener noreferrer"&gt;https://github.com/Mustafa1765/challange--2-26-hcober&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local Dev Server:&lt;/strong&gt; &lt;code&gt;http://127.0.0.1:8000&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Demo Highlights:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Menu Studio:&lt;/strong&gt; Browse authentic menus from Rome (&lt;em&gt;Trattoria Da Cesare&lt;/em&gt;), Kyoto (&lt;em&gt;Kappo Izakaya Gion&lt;/em&gt;), and India (&lt;em&gt;Malabar Coast Spice Kitchen&lt;/em&gt;). Select any target language (Japanese, Spanish, French, German, Mandarin, Italian, Korean, Arabic, Portuguese) to watch dish names, sensory flavor notes, culinary heritage stories, and dining etiquette render in real-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Guest QR Menu:&lt;/strong&gt; Diners scan the simulated table QR code to view a mobile-optimized dining menu. Check &lt;em&gt;"Hide Gluten"&lt;/em&gt;, &lt;em&gt;"Hide Dairy"&lt;/em&gt;, or &lt;em&gt;"Show Only Halal"&lt;/em&gt;, and conflicting dishes disappear instantly from the guest's view.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TabPFN Tourist Demand Forecaster:&lt;/strong&gt; Input demographic features (party size, origin region, dining slot, spice tolerance, dietary restrictions) to forecast dish demand categories, predict allergen escalation probabilities, and recommend kitchen prep quantities.&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;The complete source code is open-source under the MIT License:&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/Mustafa1765" rel="noopener noreferrer"&gt;
        Mustafa1765
      &lt;/a&gt; / &lt;a href="https://github.com/Mustafa1765/challange--2-26-hcober" rel="noopener noreferrer"&gt;
        challange--2-26-hcober
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &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;BistroLocal AI 🍲✨&lt;/h1&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Hyper-Localized Cultural Menu Translator, Allergen Safety Guardian &amp;amp; TabPFN Tabular Dining Forecaster&lt;/strong&gt;
&lt;em&gt;Submission for Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://fastapi.tiangolo.com" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/41637ead3df8cf2e2f6589f103ec2d5c92edd0f0a7fbbf81d287aeaed09807c1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466173744150492d302e3131352b2d3030393638382e7376673f6c6f676f3d66617374617069266c6f676f436f6c6f723d7768697465" alt="FastAPI"&gt;&lt;/a&gt;
&lt;a href="https://platform.priorlabs.ai" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/f9a21b12b3df1a6cb2e7f50ccdc3f61bae45efb9fa42c82b25d6ade6d551bd4f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f54616250464e2d332e35253230466f756e646174696f6e2532304d6f64656c2d3841324245322e737667" alt="TabPFN"&gt;&lt;/a&gt;
&lt;a href="https://ollama.ai" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/f1caeebf5697bb51511893ee0bd92b104dcac418f53efa61b776fab06fa230f2/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4f6c6c616d612d4f70656e2d2d576569676874732d626c61636b2e7376673f6c6f676f3d6f6c6c616d61266c6f676f436f6c6f723d7768697465" alt="Ollama"&gt;&lt;/a&gt;
&lt;a href="https://opensource.org/licenses/MIT" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎯 The Problem &amp;amp; The Side Hustle Opportunity&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;The Pain Point&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;Every year, millions of international travelers visit local trattorias in Rome, izakayas in Kyoto, taco stalls in Oaxaca, and spice bistros in Kerala.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Google Translate Butcheries&lt;/strong&gt;: Generic translation destroys culinary heritage. Translating &lt;em&gt;Penne all'Arrabbiata&lt;/em&gt; as &lt;em&gt;"Angry Pens"&lt;/em&gt; or &lt;em&gt;Nasu Dengaku&lt;/em&gt; into &lt;em&gt;"Eggplant Field"&lt;/em&gt; alienates diners and trivializes the chef's craft.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden Allergen &amp;amp; Dietary Nightmares&lt;/strong&gt;: Tourists with severe celiac disease, nut allergies, or religious dietary requirements (Halal, Kosher, Vegan) suffer extreme anxiety. A mistranslated fish paste or wheat thickening agent can trigger anaphylaxis or ruin a diner's trip.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chefs Protect Their Recipes&lt;/strong&gt;: Independent chefs fiercely guard proprietary spice blends, secret family sauces, and local suppliers. They flatly refuse to upload confidential…&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Mustafa1765/challange--2-26-hcober" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Core Architecture
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; Python 3, FastAPI, Uvicorn, Pydantic, HTTPX.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Core (Language &amp;amp; Culture):&lt;/strong&gt; Open-weight models (Llama 3.2, Qwen 2.5 via local Ollama) + offline culinary intelligence RAG heuristics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Core (Tabular Forecasting):&lt;/strong&gt; &lt;strong&gt;TabPFN-3.5&lt;/strong&gt; (Prior Labs' Tabular Foundation Model) + local Scikit-Learn tabular ensemble fallback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; Vanilla HTML5 &amp;amp; bespoke Vanilla CSS dark-mode glassmorphic design system with zero external UI framework dependencies.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;BistroLocal AI is architected around two complementary open-source AI engines:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Local Open-Weight Culinary Translation Engine (&lt;code&gt;backend/engine/translator.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Rather than doing literal word substitution, our culinary engine dissects each dish into 5 distinct dimensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentic Local Title with Phonetic Guide:&lt;/strong&gt; Preserves the cultural name while providing phonetic pronunciation (e.g. &lt;em&gt;Cacio e Pepe [KAH-choh eh PEH-peh]&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sensory Tasting Notes:&lt;/strong&gt; Explains mouthfeel, texture, and aroma in the diner's native tongue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cultural Heritage &amp;amp; Terroir:&lt;/strong&gt; Explains the historical origin of the recipe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traditional Technique:&lt;/strong&gt; Details how the kitchen crafted the dish.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dining Etiquette:&lt;/strong&gt; Offers tips on traditional pairings and how to eat the dish like a local.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The backend queries local &lt;strong&gt;Ollama&lt;/strong&gt; (&lt;code&gt;http://127.0.0.1:11434&lt;/code&gt;) running compact, powerful open-weight models (&lt;code&gt;llama3.2&lt;/code&gt;, &lt;code&gt;qwen2.5&lt;/code&gt;). If Ollama is offline or running on a restricted POS terminal, BistroLocal AI smoothly falls back to an internal deterministic regional culinary dictionary with zero latency.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Big-14 Allergen Guardian (&lt;code&gt;backend/engine/allergen_detector.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Scans raw ingredient strings to detect the &lt;strong&gt;Big 14 EU/FDA allergens&lt;/strong&gt; (&lt;em&gt;Gluten, Crustaceans, Eggs, Fish, Peanuts, Soybeans, Milk, Tree Nuts, Celery, Mustard, Sesame, Sulphites, Lupin, Molluscs&lt;/em&gt;), tags religious/ethical dietary compatibility (&lt;em&gt;Halal-Friendly, Kosher-Friendly, Vegan, Vegetarian, Gluten-Free&lt;/em&gt;), and flags cross-contact hazards like shared fryers.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. TabPFN-3.5 Tabular Intelligence Agent (&lt;code&gt;backend/engine/tabpfn_predictor.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Generic LLMs are notorious for hallucinating numbers when processing tabular records. We integrated &lt;strong&gt;Prior Labs' TabPFN-3.5&lt;/strong&gt;, a state-of-the-art foundation model designed specifically for tabular data.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dataset (&lt;code&gt;backend/data/dining_history.csv&lt;/code&gt;):&lt;/strong&gt; Historical table records tracking party size, tourist origin region, dining time slot, season, spice tolerance, dietary profiles, and ordered dish categories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predictions Made:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dish Preference Probabilities:&lt;/strong&gt; Full probability distribution across dish types for incoming tables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allergen Escalation Risk Score (0–100%):&lt;/strong&gt; Predicts the likelihood that a table will require custom kitchen intervention or allergen substitution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily Prep Servings Regression:&lt;/strong&gt; Estimates prep batch volumes to help kitchen staff prevent food waste.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌟 Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Open innovation is not just a nice-to-have for this project—&lt;strong&gt;it is the fundamental reason this side hustle works&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Edge &amp;amp; Offline Resilience:&lt;/strong&gt; Many of the best restaurants in the world are tucked into historic stone alleys, ancient cellars, or street food stalls with spotty or nonexistent Wi-Fi. BistroLocal AI runs 100% on a laptop or local terminal without requiring an internet connection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Absolute Recipe Confidentiality:&lt;/strong&gt; Chefs will not compromise their intellectual property. With open-weight models running on local hardware, sensitive recipe formulations never traverse the internet or get fed into closed cloud training sets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infinite Margin Economics:&lt;/strong&gt; In closed-API architectures, your recurring cost scales linearly with usage. Every menu tweak or translation request drains tokens. With open-source models, your marginal cost is &lt;strong&gt;$0.00&lt;/strong&gt;. This makes a $39/month SaaS fee almost 100% pure profit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Vendor Lock-In or Sudden Price Hikes:&lt;/strong&gt; Closed APIs deprecate endpoints, change pricing tiers, or enforce restrictive content filters on cultural dish names. With open-weight AI, the model belongs to the restaurant owner forever.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  💬 My First User
&lt;/h2&gt;

&lt;p&gt;To test BistroLocal AI in the real world, I visited Marco, the owner of a small Roman-style trattoria in my local area that gets heavy foot traffic from international university students and tourists.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Happened:
&lt;/h3&gt;

&lt;p&gt;I uploaded his 12-item pasta and secondi menu into BistroLocal AI. Within seconds, his dishes were translated into Japanese, Spanish, and French, complete with authentic pronunciations and cultural origin notes.&lt;/p&gt;

&lt;p&gt;When Marco saw how the system flagged the Pecorino cheese for dairy allergies, the guanciale for non-Halal pork warnings, and the tonnarelli for gluten—and then saw the &lt;strong&gt;Guest QR View&lt;/strong&gt; allow diners to filter dishes with a single tap—his eyes lit up:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Every Friday night, my waitstaff spends 15 minutes per table trying to explain in broken English what guanciale is and whether the pasta has nuts in it. This QR menu answers all of it before the waiter even reaches the table."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Did he pay?
&lt;/h3&gt;

&lt;p&gt;Marco agreed to test the QR codes on 5 of his tables for the weekend. He said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"If this saves my servers from having to explain the menu to tourists every rush, I'd gladly pay $35 or $40 a month. What I really want next is a one-click button to print daily seasonal specials straight from the iPad."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That feedback confirmed the core thesis: &lt;strong&gt;real businesses will gladly pay for small, specific, and privacy-respecting AI tools that solve their everyday operational headaches.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🏆 Prize Categories
&lt;/h2&gt;

&lt;p&gt;I am entering BistroLocal AI for the following partner prize categories:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Best Use of TabPFN ($200 USD)
&lt;/h3&gt;

&lt;p&gt;We used Prior Labs' &lt;strong&gt;TabPFN-3.5 foundation model&lt;/strong&gt; (&lt;code&gt;tabpfn-client&lt;/code&gt;) inside our prediction engine to forecast tourist dish preferences, assess kitchen allergen escalation risks, and predict prep quantities from historical dining CSV tables. The system connects to the TabPFN platform while maintaining a robust local tabular fallback.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Best Use of Render ($200 USD)
&lt;/h3&gt;

&lt;p&gt;We configured a production-ready &lt;strong&gt;Render Blueprint (&lt;code&gt;render.yaml&lt;/code&gt;)&lt;/strong&gt; and optimized containerized &lt;code&gt;Dockerfile&lt;/code&gt; for instant 1-click cloud deployment on Render's Web Service platform.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with open-source AI, local open-weight models, and TabPFN for Hacktoberfest 2026.&lt;/em&gt; 🚀&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I built a self-hosted gig watcher so I stop refreshing job boards — it only pings me on new matches</title>
      <dc:creator>earnnova-dev</dc:creator>
      <pubDate>Tue, 13 Oct 2026 19:13:30 +0000</pubDate>
      <link>https://dev.to/earnnovadev/i-built-a-self-hosted-gig-watcher-so-i-stop-refreshing-job-boards-it-only-pings-me-on-new-matches-3111</link>
      <guid>https://dev.to/earnnovadev/i-built-a-self-hosted-gig-watcher-so-i-stop-refreshing-job-boards-it-only-pings-me-on-new-matches-3111</guid>
      <description>&lt;p&gt;Freelancers lose real money to latency. The best remote gigs get filled in the first few hours — the "Senior Backend Engineer, $120k, fully remote" posting is usually taken before you finish your second coffee. So we all do the same embarrassing thing: keep 6 job boards open and refresh every 15–20 minutes, mostly seeing the same 300 stale listings.&lt;/p&gt;

&lt;p&gt;I got tired of it, so I built &lt;strong&gt;GigWatch&lt;/strong&gt; — a small, self-hosted watcher that monitors live job/gig feeds, filters them against &lt;em&gt;your&lt;/em&gt; skills, remembers what it has already shown you, and pings you (console, email, or Slack) &lt;strong&gt;only when a new matching gig actually appears&lt;/strong&gt;. No dashboard to babysit. No account to sign up for. Just a process on a machine you already run.&lt;/p&gt;

&lt;p&gt;Install is one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;gigwatch-nova
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's Python 3.9+, self-hosted, and pulls from free, keyless job endpoints (Remotive, We Work Remotely, RemoteOK, Jobicy, Hacker News, plus any RSS feed you point it at). No API keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  The whole idea in four steps
&lt;/h2&gt;

&lt;p&gt;GigWatch does one loop, on a timer you control (default 15 min):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fetch&lt;/strong&gt; — pull live listings from each configured source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Score&lt;/strong&gt; — match each listing against your skills/title/keywords and score the fit (0–10).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dedup&lt;/strong&gt; — compare against a local state file of everything it has already shown you. This is the part that makes it not-spammy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alert&lt;/strong&gt; — only fire (console line, email, or Slack) for &lt;em&gt;new&lt;/em&gt; matches above your score floor.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The dedup step is the whole point. A job board shows you the same 300 listings forever; GigWatch shows you a listing exactly once, and only if it matches your profile.&lt;/p&gt;

&lt;h2&gt;
  
  
  The config you actually write
&lt;/h2&gt;

&lt;p&gt;Everything is a single JSON file. A realistic one looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"remotive"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wwr"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"remoteok"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jobicy"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hn"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rss"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.python.org/jobs/feed/rss/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"profile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Senior Software Engineer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skills"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"backend"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"remote"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"notes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"senior, $150k+"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"filters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"backend"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"django"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fastapi"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"require_all_keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"min_score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"exclude_keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"intern"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"junior"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"alerts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"console"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${GIGWATCH_EMAIL_TO}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"smtp_host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"smtp.example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"smtp_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;587&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"use_tls"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${GIGWATCH_SMTP_USER}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${GIGWATCH_SMTP_PASS}"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"slack"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"webhook_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${GIGWATCH_SLACK_WEBHOOK}"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"max_per_alert"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"state_file"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gigwatch-state.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"poll_interval"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things I'd tune before you trust it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;exclude_keywords&lt;/code&gt;&lt;/strong&gt; is your friend. &lt;code&gt;"intern"&lt;/code&gt;, &lt;code&gt;"junior"&lt;/code&gt;, &lt;code&gt;"contract-only"&lt;/code&gt; — whatever you will never want, put it here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;min_score&lt;/code&gt;&lt;/strong&gt; is the noise dial. Start at 1.0, bump it up if you're still getting too much.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;require_all_keywords&lt;/code&gt;&lt;/strong&gt; — set it to &lt;code&gt;true&lt;/code&gt; if you only want listings that hit &lt;em&gt;every&lt;/em&gt; one of your keywords (much quieter, fewer false positives).&lt;/li&gt;
&lt;li&gt;Secrets go in env vars (&lt;code&gt;${GIGWATCH_SMTP_PASS}&lt;/code&gt;), not in the JSON. That keeps your config file safe to commit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why it's not another job board
&lt;/h2&gt;

&lt;p&gt;The free endpoints that power it are &lt;em&gt;keyless and public&lt;/em&gt; — they're the same feeds a job aggregator would use. That's a strength (nothing to register, nothing to break auth on) and a known limitation, so let me be honest about what it covers and what it doesn't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Remotive, We Work Remotely, RemoteOK, Jobicy, Hacker News, and any RSS feed you add.&lt;/li&gt;
&lt;li&gt;✅ Any board that exposes a JSON or RSS feed you can point it at.&lt;/li&gt;
&lt;li&gt;❌ Upwork, LinkedIn, and other gated platforms that require a logged-in account. Those need authenticated scraping, which is a whole separate (and fragile) project. GigWatch is built for the open feed world on purpose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If most of your gigs come from a gated platform, the open-feed watcher is still useful as a &lt;em&gt;secondary&lt;/em&gt; channel — it catches the listings the gated boards re-post, which is often a meaningful share.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CI version: let a schedule post matches as an Issue
&lt;/h2&gt;

&lt;p&gt;If you'd rather not run a daemon, I ship a GitHub Action. It fetches live jobs filtered by skill and returns them as Markdown, so a scheduled workflow can open a fresh Issue (or PR comment) with the day's new matches. No API keys — it's powered by the same free feed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gig-watch&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;7&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;   &lt;span class="c1"&gt;# 07:00 UTC daily&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Scan feeds for matching gigs&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;earnnova-dev/gigwatch@main&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;scan&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;skills&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python,backend,api&lt;/span&gt;
          &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
          &lt;span class="na"&gt;min_score&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Open an issue with the matches&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;steps.scan.outputs.job_count &amp;gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/github-script@v7&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;github.rest.issues.create({&lt;/span&gt;
              &lt;span class="s"&gt;owner: context.repo.owner,&lt;/span&gt;
              &lt;span class="s"&gt;repo: context.repo.repo,&lt;/span&gt;
              &lt;span class="s"&gt;title: `New matching gigs (${context.run_id})`,&lt;/span&gt;
              &lt;span class="s"&gt;body: `${{ steps.scan.outputs.markdown }}`&lt;/span&gt;
            &lt;span class="s"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Point it at your own repo, and every morning you get a clean, searchable Issue of the day's new matching gigs. The state file makes the action idempotent, so it only ever posts &lt;em&gt;new&lt;/em&gt; stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;It's a watcher, not a scraper-with-everything. You host it; it does not phone home.&lt;/li&gt;
&lt;li&gt;Feed coverage is limited to what's publicly keyless. Gated platforms are out of scope by design.&lt;/li&gt;
&lt;li&gt;It scores by keyword overlap, not by an LLM. Good enough to filter noise; not a replacement for actually reading the listing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;gigwatch-nova
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Requires Python 3.9+. Drop in a &lt;code&gt;config.json&lt;/code&gt; like the one above, point &lt;code&gt;state_file&lt;/code&gt; somewhere writable, and run it under cron or your scheduler of choice. If the whole "watch the open feeds, dedup against what I've seen, ping me on new matches" thing matches your workflow, it's a few minutes to stand up — and your browser tabs can finally close.&lt;/p&gt;

</description>
      <category>python</category>
      <category>selfhosted</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
