<?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: Arya Koste</title>
    <description>The latest articles on DEV Community by Arya Koste (@arya_koste_5845807df94776).</description>
    <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3396126%2Fff57b4f1-4d36-4ad9-8621-d0c4fd20823a.png</url>
      <title>DEV Community: Arya Koste</title>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.clauneck.workers.dev/feed/arya_koste_5845807df94776"/>
    <language>en</language>
    <item>
      <title>Choosing a Vector Database in 2026: pgvector vs. Pinecone vs. Qdrant vs. Weaviate vs. Milvus</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Wed, 24 Jun 2026 17:56:49 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/choosing-a-vector-database-in-2026-pgvector-vs-pinecone-vs-qdrant-vs-weaviate-vs-milvus-422k</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/choosing-a-vector-database-in-2026-pgvector-vs-pinecone-vs-qdrant-vs-weaviate-vs-milvus-422k</guid>
      <description>&lt;p&gt;Every RAG tutorial pulls the same move. It walks you through embeddings, chunking, retrieval, and then right at the moment of truth it says "now pick a vector database" and just... moves on. Like that's a coffee-order decision. Like you're choosing a font.&lt;/p&gt;

&lt;p&gt;It's not. The database you pick decides how fast your queries come back, how much you bleed in infrastructure costs, and how miserable your life gets the day traffic triples. And here's the thing that took me a while to figure out while researching this: the database you start with is often not the one you ship. Teams migrate, sometimes more than once. Some of those moves are clean wins; some are weeks of pain and a postmortem doc.&lt;/p&gt;

&lt;p&gt;So let's try to skip the regret. I spent a long time digging through benchmarks, production write-ups, and the trade-offs people only discover after the fact, and this is the guide I wish I'd had when I started: what each of these five (pgvector, Pinecone, Qdrant, Weaviate, and Milvus) is actually good at, where each quietly falls apart, and how to pick without drowning in a feature matrix.&lt;/p&gt;

&lt;p&gt;I'll spoil the ending, because it's the most useful thing here: &lt;strong&gt;pick based on the infrastructure you already run, not the benchmark you just read.&lt;/strong&gt; If you're already on Postgres, the answer is probably pgvector and you can almost stop reading. If you never want to touch infrastructure again, it's Pinecone. Everything past that is fine-tuning.&lt;/p&gt;




&lt;h2&gt;
  
  
  The cheat sheet, for the impatient
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;If this is you&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;th&gt;The one-liner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Already on Postgres, under ~50M vectors&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;pgvector&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One database, zero new problems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Want it to just work, will pay for that&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Pinecone&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hand them a key, walk away&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Self-hosting and obsessed with speed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Qdrant&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The Rust one. It's fast.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hybrid search is the whole point&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Weaviate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Did keyword + vector before it was cool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heading toward a billion vectors&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Milvus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built for the scale that breaks everything else&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now the actual reasoning.&lt;/p&gt;




&lt;h2&gt;
  
  
  First, stop staring at the benchmarks
&lt;/h2&gt;

&lt;p&gt;I get the pull. The benchmarks are right there, with their satisfying little bar charts, and one database is 3ms faster than another and that &lt;em&gt;feels&lt;/em&gt; like a decision. It mostly isn't. At the scale almost everyone actually operates, every database on this list is fast enough that your users will never feel the difference. The latency war is largely fought over workloads you don't have yet.&lt;/p&gt;

&lt;p&gt;What actually decides this, in roughly this order, is four boring questions:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What do you already run?&lt;/strong&gt; If Postgres is already humming along in your stack (and if you're a full-stack dev, it probably is), bolting on a second database means a sync layer, separate backups, and a whole new thing that can page you at 3am. That gravity is real, and it usually wins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do you want to run infrastructure at all?&lt;/strong&gt; Some people find ops satisfying. Some people would rather light money on fire than configure another cluster. Both are valid. Be honest about which one you are.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How big does this actually get?&lt;/strong&gt; Under 10 million vectors, genuinely anything works. Between 10 million and a billion, the field thins out fast. Past a billion, you've got maybe two real options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do you need hybrid search?&lt;/strong&gt; This one sneaks up on people. Pure semantic search is great until a user types an exact product ID or a version number and your "vibes-based" retrieval shrugs. More on this later, but file it away.&lt;/p&gt;

&lt;p&gt;Answer those four honestly and the database basically picks itself. Here's each one against that lens.&lt;/p&gt;




&lt;h2&gt;
  
  
  pgvector: the answer that's almost boring enough to be right
&lt;/h2&gt;

&lt;p&gt;pgvector isn't a database. It's a Postgres extension. You teach the database you already have how to do vector search, and that's the whole trick. No new service. No sync layer. No 2am pages from a system you provisioned in a hurry and never fully understood.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's so often the right call.&lt;/strong&gt; Your vectors sit right next to your actual data, so you can query both in a single transaction, your existing backups already cover them, and filtering is just a SQL &lt;code&gt;WHERE&lt;/code&gt; clause: joins, subqueries, the works. The old "Postgres is too slow for vectors" complaint is genuinely outdated; it comes from the bad-old-days IVFFlat era. Once HNSW indexing landed, pgvector started matching dedicated databases at a million vectors, and with the pgvectorscale extension it holds its own well past that, with competitive throughput at 99% recall on tens of millions of vectors. For a huge share of RAG projects this is the right answer, and its only real crime is being unexciting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it starts to hurt.&lt;/strong&gt; Push past a couple million vectors on one box and index builds start taking twenty-plus minutes, and Postgres's VACUUM process starts elbowing your queries for resources. There's also a subtler trap: pgvector filters &lt;em&gt;after&lt;/em&gt; it searches, so a picky filter on a big collection means scanning a pile of candidates to hand you back a handful. Somewhere around 50-100 million vectors you'll be reaching for read replicas, partitioning, or the exit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it if:&lt;/strong&gt; you're on Postgres, under ~50M vectors, and you don't need to win a latency contest. Most teams are exactly this and don't realize it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pinecone: pay money, make the problem disappear
&lt;/h2&gt;

&lt;p&gt;Pinecone basically invented the managed-vector-database category and still sets the bar for it. You get an API key, you make an index, you throw vectors at it, you query them back. There's nothing to size, nothing to tune, nothing to keep alive. That's not a feature list. That's the entire pitch, and it's a genuinely good one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why people love it.&lt;/strong&gt; "I need a vector database and I refuse to think about it any further" is a completely legitimate position, and Pinecone is built precisely for that person. It scales to billions of vectors, it does hybrid search, it's got the enterprise compliance checkboxes. You offload the whole operational headache to someone whose entire job is keeping it up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The catch (and there's a real one).&lt;/strong&gt; It's closed-source and there's no self-hosting, full stop. Your data lives in their cloud, and if their pricing shifts or they have a bad day, you have no plan B. The serverless tier swaps latency for convenience and pins your recall at around 90% with no knob to turn. Pinecone just doesn't let you touch the HNSW internals. Writes are eventually consistent, so freshly-added vectors take a beat to show up. Filtering is weaker than SQL (no joins, no subqueries), so anything fancy spills back into your application code. And the bill grows with you, sometimes faster than you'd like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it if:&lt;/strong&gt; not running infrastructure matters more to you than tuning control, and you've made peace with lock-in as the price of never thinking about this again.&lt;/p&gt;




&lt;h2&gt;
  
  
  Qdrant: the fast one, and it knows it
&lt;/h2&gt;

&lt;p&gt;Qdrant is open-source, written in Rust, and built from day one to do vector search and basically nothing else. That focus shows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's appealing.&lt;/strong&gt; It's the speed leader of the open-source pack, with the lowest p50 latency of the bunch, and the gap actually widens under heavy query load where it matters most. But the real party trick is filtered search: Qdrant runs your filters &lt;em&gt;inside&lt;/em&gt; the search traversal instead of bolting them on afterward, so the exact "find me similar shoes, but only the red ones in stock" query that makes pgvector sweat stays snappy here. Add binary quantization that can shrink memory dramatically, plus newer cloud features like GPU-accelerated indexing and multi-AZ failover, and you've got a lot of database for the money. The free tier is the most generous on this list, too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The honest downside.&lt;/strong&gt; The ecosystem is younger. You'll find fewer Stack Overflow threads at midnight, fewer random blog posts that happen to solve your exact problem. Though LangChain and LlamaIndex both support it just fine, so you're not in the wilderness. And some teams have reported friction under really heavy concurrent writes, so if you're write-hammering it, test that specifically before you commit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it if:&lt;/strong&gt; you'll happily run your own infrastructure, you want the best performance per dollar, and fast filtered search is central to what you're building.&lt;/p&gt;




&lt;h2&gt;
  
  
  Weaviate: the one that wants to be your whole pipeline
&lt;/h2&gt;

&lt;p&gt;Weaviate is open-source too, but it's playing a different game. It doesn't just want to store your vectors, it wants to be the backbone of your entire AI pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it stands out.&lt;/strong&gt; Two reasons. First, hybrid search, which Weaviate shipped back in late 2022, ages before most of the field caught on. Its implementation is genuinely mature (proper keyword scoring fused with vector results), so if blending semantic and exact-match retrieval is core to your product, this is the most grown-up native option out there. Second, it'll do your embeddings for you: send raw text, and Weaviate vectorizes it on the way in using OpenAI, Cohere, Hugging Face, whatever. Fewer moving parts in your pipeline, which is a real quality-of-life win.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where it gets heavy.&lt;/strong&gt; Those built-in vectorizers aren't free. They call the same embedding APIs you'd call yourself, so you're paying that latency and cost, just somewhere less visible. The GraphQL API is a genuine learning curve if your brain is wired for SQL or plain REST. And the Java runtime is hungry when you self-host; operational complexity climbs as you pile on modules and multi-tenancy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it if:&lt;/strong&gt; native hybrid search is a hard requirement, or you genuinely want the database to handle vectorization so your pipeline has fewer parts to break.&lt;/p&gt;




&lt;h2&gt;
  
  
  Milvus: bring this one out when things get enormous
&lt;/h2&gt;

&lt;p&gt;Milvus is the most-starred open-source option on GitHub, backed by Zilliz (whose managed Zilliz Cloud is the souped-up enterprise version). It exists for one reason: scale that makes everything else fall over.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it earns its place.&lt;/strong&gt; Nothing else here touches its distributed architecture when you're genuinely big. Heading past a billion vectors? Need GPU-accelerated indexing? This is the tool built for that exact day. At the 100M+ range it's a serious candidate, full stop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why you shouldn't reach for it casually.&lt;/strong&gt; It's a lot of machine. The operational complexity outpaces Qdrant's for normal use cases. Budget real engineering time for the Kubernetes wrangling, and expect your team to climb a learning curve. There's also a known performance gotcha around output fields that can bite in RAG pipelines. If you're under a few tens of millions of vectors, Milvus is almost certainly more database than your problem deserves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use it if:&lt;/strong&gt; you're truly heading into 100M-1B+ territory or need distributed GPU indexing, and you've got the ops capacity to run it.&lt;/p&gt;




&lt;h2&gt;
  
  
  A quick word on the ones I skipped
&lt;/h2&gt;

&lt;p&gt;ChromaDB earns an honorable mention. It runs right inside your Python process with zero config and is a joy for prototyping. It just doesn't bring the production tooling (high availability, snapshots, real monitoring) the big five do, so think of it as where you start, not where you stay. Faiss (a library, not a database), LanceDB (multi-modal first), Vespa, and the cloud-native managed options like Vertex Vector round out the wider field, but the five above are the ones people actually argue about in production Slack channels.&lt;/p&gt;




&lt;h2&gt;
  
  
  The hybrid-search thing I keep promising to explain
&lt;/h2&gt;

&lt;p&gt;Here it is, because it quietly decides more choices than people expect. Pure vector search is wonderful right up until someone searches for an exact SKU, a person's name, or "v2.3.1", and suddenly your beautiful semantic embeddings return something thematically adjacent but useless. Real systems need both: the fuzzy semantic match &lt;em&gt;and&lt;/em&gt; the exact keyword hit, in the same query.&lt;/p&gt;

&lt;p&gt;Weaviate and Qdrant ship this natively. Pinecone bolted it on. pgvector makes you assemble it yourself by hand. If you're building agent memory or RAG over genuinely varied content, treat hybrid search as non-negotiable and let it tilt your decision. It's not a nice-to-have anymore; it's table stakes wearing a trench coat pretending to be a differentiator.&lt;/p&gt;




&lt;h2&gt;
  
  
  So, what do you actually pick?
&lt;/h2&gt;

&lt;p&gt;If you take one thing from all of this:&lt;/p&gt;

&lt;p&gt;You're on Postgres and under ~50M vectors? Use &lt;strong&gt;pgvector&lt;/strong&gt; and go build something. Stop researching.&lt;/p&gt;

&lt;p&gt;You never want to see a config file? &lt;strong&gt;Pinecone&lt;/strong&gt;, and make peace with the lock-in.&lt;/p&gt;

&lt;p&gt;Self-hosting and you care about speed or filtering? &lt;strong&gt;Qdrant&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Hybrid search is the heart of the product? &lt;strong&gt;Weaviate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Staring down hundreds of millions of vectors? &lt;strong&gt;Milvus&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And the meta-lesson under all of it: the benchmarks are tie-breakers, not deciders. The database you prototype with probably isn't the one you'll ship, so optimize for the one that's easiest to reason about today and least painful to leave tomorrow. For most teams, honestly, that's pgvector right up until something specific drags them off it. And "something specific" tends to arrive a lot later than the breathless blog posts would have you believe.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;One fair warning on the numbers in here: the benchmark figures floating around the industry come from wildly different test setups: different vector dimensions, different hardware, different recall targets, and quite often run by the vendor whose database happens to win. Treat all of it as directionally true rather than gospel, and test against your own data at your own scale before you bet the product on it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>database</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Building a 3D Game in the Browser Humbled Me. Here's Everything That Fought Back.</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Sun, 21 Jun 2026 19:32:38 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/building-a-3d-game-in-the-browser-humbled-me-heres-everything-that-fought-back-4mmg</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/building-a-3d-game-in-the-browser-humbled-me-heres-everything-that-fought-back-4mmg</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.clauneck.workers.dev/challenges/june-game-jam-2026-06-03"&gt;June Solstice Game Jam&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Coordinate systems. Rotated bounding boxes. A sine wave cycling 637 times per second. A tribute to Alan Turing hidden in binary light. This is how Solstice Village came to be.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Idea
&lt;/h2&gt;

&lt;p&gt;June 21. The longest day. Light and darkness at their most dramatic inflection point.&lt;/p&gt;

&lt;p&gt;I wanted something that &lt;em&gt;felt&lt;/em&gt; like the solstice — not a platformer about suns, not a timer counting daylight seconds. I wanted the quiet tension of a village where every window has gone dark on the longest night, and the warmth that spreads as you, one courier with a lantern, carry light back home to home.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solstice Village&lt;/strong&gt; is a 3D exploration game built in Three.js. You play as Sol, walking a circular village, talking to keepers, gathering light at the central brazier, and lighting eight dark homes until the sky shifts from midnight indigo to morning gold.&lt;/p&gt;

&lt;p&gt;Play it here: &lt;a href="https://aryakoste.github.io/solsticeGame/" rel="noopener noreferrer"&gt;https://aryakoste.github.io/solsticeGame/&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What You're Actually Playing
&lt;/h2&gt;

&lt;p&gt;The village is a ring. At the centre: a brazier that flickers. Around it at radius 17 units: eight homes, each dark. Between them at radius 11.5: lamp posts. Beyond the homes: 32 swaying trees, fireflies, a deer, a cat, an owl blinking on a post, and — if you find it — a secret grove with glowing mushrooms and a standing stone.&lt;/p&gt;

&lt;p&gt;The main game loop is: &lt;strong&gt;Talk → Gather → Deliver → Watch the sky change.&lt;/strong&gt; Each house lit raises &lt;code&gt;dawnAmount&lt;/code&gt; by 1/8. That single float drives everything — sky colour, sun position, fog, ambient light, moon fade. The world literally brightens as you play.&lt;/p&gt;

&lt;p&gt;But there is a second ending. If you collect all six spirit wisps scattered around the village without lighting a single home, the game takes a different turn entirely. The village stays dark. The grove awakens. The stone hums. A different piece of narration plays. It rewards the player who ignores the instructions and wanders instead — which felt right for a solstice game, where the night itself has value.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why 3D on the Web Is a Different Beast Entirely
&lt;/h2&gt;

&lt;p&gt;Most developers who've shipped 2D browser games look at a 3D game and think: &lt;em&gt;it's just one more axis, how much harder can it be?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The answer is: in almost every possible way.&lt;/p&gt;

&lt;p&gt;In 2D, your world is flat. Movement is &lt;code&gt;x += vx&lt;/code&gt;. Collision is rectangle overlap. Camera is a viewport offset. You render sprites front-to-back and call it done. The computer does what your intuition expects.&lt;/p&gt;

&lt;p&gt;In 3D, almost nothing does what your intuition expects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Everything lives in multiple coordinate spaces at once.&lt;/strong&gt; Your player exists in world space. The camera that watches them exists in view space. Objects like houses have their own local space, rotated relative to the world. When you need to know if the player is colliding with a rotated house, you can't just compare coordinates — you have to transform the player into the house's local space, do the math there, then rotate the result back. Get any step wrong and the player clips through walls or gets ejected into the sky.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rotations stop being numbers and become order-dependent operations.&lt;/strong&gt; In 2D, rotating by 30° then 45° gives the same result as rotating by 45° then 30°. In 3D, the order matters. Rotation around X then Y is not the same as Y then X. This is not a quirk — it's fundamental to how 3D rotations work (they aren't commutative). Every character, every NPC, every camera angle in a 3D game is a product of carefully ordered rotations, and one wrong assumption cascades into every object in the scene pointing the wrong direction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The camera is its own 3D object, not a window.&lt;/strong&gt; In 2D you scroll a viewport. In 3D, your camera has a position, an orientation, a field of view, a near clip plane, a far clip plane. A third-person camera orbiting a player requires converting spherical coordinates (yaw angle, pitch angle, distance) into Cartesian (x, y, z). That formula is six trigonometry calls per frame, and if any sign is wrong the camera clips underground, or drifts into the player's head, or spins the wrong direction when you drag the mouse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lighting is a full second discipline.&lt;/strong&gt; In 2D you colour pixels. In 3D, light sources emit in all directions, cast shadows that require their own depth-buffer render pass, bounce off surfaces according to material properties (roughness, metalness, normal maps), and interact with ambient light, hemisphere light, and fog — all simultaneously. Getting a scene to &lt;em&gt;feel&lt;/em&gt; right at night, then &lt;em&gt;feel&lt;/em&gt; like dawn, requires understanding all of those systems well enough to tune them together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time is not a given.&lt;/strong&gt; In 2D games you often get away with &lt;code&gt;position += speed&lt;/code&gt; per frame. In 3D you quickly learn that frame rate varies — a phone runs at 30fps, a desktop at 120fps — and if you animate against raw time without delta-time scaling, your game runs fast on powerful hardware and slow on weak hardware. And even delta-time isn't enough: the specific unit of time matters. Miss a milliseconds-to-seconds conversion anywhere and your animation blows up in ways that look completely inexplicable until you work out the arithmetic.&lt;/p&gt;

&lt;p&gt;These aren't beginner mistakes you outgrow. They are the permanent operational cost of building in three dimensions. Every feature you add has to be thought through in all three axes, across multiple coordinate spaces, accounting for arbitrary rotation and variable time. And you discover most of them by shipping a bug.&lt;/p&gt;

&lt;p&gt;Here's what Solstice Village taught me.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Technical Part (Where the 3D Tax Got Collected)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Challenge 1: The NPC That Stared at Walls
&lt;/h3&gt;

&lt;p&gt;Every NPC was placed around the village ring facing &lt;em&gt;away&lt;/em&gt; from the plaza — backs to the player, faces to their own house wall. Maddening.&lt;/p&gt;

&lt;p&gt;The culprit: &lt;code&gt;Three.js r128&lt;/code&gt;'s &lt;code&gt;Object3D.lookAt()&lt;/code&gt;. This is exactly the kind of 3D convention trap that costs hours. &lt;code&gt;lookAt&lt;/code&gt; on any object makes the &lt;strong&gt;local −Z axis&lt;/strong&gt; face the target — the camera convention carried over from OpenGL, where cameras look down -Z by default. When you call &lt;code&gt;grp.lookAt(0,0,0)&lt;/code&gt;, Three.js rotates the object so its &lt;em&gt;back&lt;/em&gt; (-Z) faces the origin. Since the character's face is built at local +Z, every NPC literally showed me their back.&lt;/p&gt;

&lt;p&gt;The fix required abandoning &lt;code&gt;lookAt&lt;/code&gt; entirely and thinking in terms of the angle I actually needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// WRONG — makes local -Z face origin (NPC backs to player)&lt;/span&gt;
&lt;span class="nx"&gt;grp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lookAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// RIGHT — makes local +Z (the face) point toward origin&lt;/span&gt;
&lt;span class="nx"&gt;grp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;atan2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;Math.atan2(dy, dx)&lt;/code&gt; gives the angle of a 2D vector. When you negate both components — &lt;code&gt;(-out.x, -out.z)&lt;/code&gt; — you get the angle pointing &lt;em&gt;toward&lt;/em&gt; the origin from the NPC's position. Since Three.js character faces have eyes at local &lt;code&gt;+Z&lt;/code&gt;, this finally made everyone look at the plaza. The same formula drives NPC head-tracking when you walk close:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Track player — local +Z toward player&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerPos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerPos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;atan2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dz&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Two negations, two formulas, same underlying geometry — just applied in opposite directions. The symmetry is elegant once you find it. Finding it is the hard part.&lt;/p&gt;


&lt;h3&gt;
  
  
  Challenge 2: The Sine Wave That Cycled 637 Times Per Second
&lt;/h3&gt;

&lt;p&gt;The cat was vibrating. The wisps were strobing. Every frame, the cat's Y position was essentially random — not glitching in some obvious broken way, just wrong, jittering too fast to see what it was trying to do.&lt;/p&gt;

&lt;p&gt;The animation code looked fine:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phase&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.06&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is where 3D's time problem came to collect. &lt;code&gt;now&lt;/code&gt; came from &lt;code&gt;performance.now()&lt;/code&gt; — which returns &lt;strong&gt;milliseconds&lt;/strong&gt;. At 60 fps, &lt;code&gt;now&lt;/code&gt; increments by ~16.7 per frame. &lt;code&gt;Math.sin(now * 4)&lt;/code&gt; means &lt;code&gt;Math.sin(16.7 × 4)&lt;/code&gt; = &lt;code&gt;Math.sin(66.8 radians)&lt;/code&gt; per frame. One full sine cycle is &lt;code&gt;2π ≈ 6.28 radians&lt;/code&gt;. So per frame, the animation was completing:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;66.8 ÷ 6.28 ≈ 10.6 full cycles per frame
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;At 60 fps, that's &lt;strong&gt;637 cycles per second&lt;/strong&gt;. The position was sampling a different, effectively random point on the sine curve every single frame. The cat wasn't jittering — it was animating perfectly at ultrasonic speed. You just can't see 637 Hz with human eyes.&lt;/p&gt;

&lt;p&gt;Fix: convert milliseconds to seconds before using as a time parameter:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Cat bob — multiply by 0.004 = (0.001 to convert ms→s) × (4 Hz frequency)&lt;/span&gt;
&lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.004&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phase&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.06&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Wisp float — explicit ms→s conversion&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.001&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;phase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;oy&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.28&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The firefly animation, written earlier, had correctly used &lt;code&gt;now * 0.001&lt;/code&gt;. The roamers and wisps were missing it. One factor of 1000. The difference between a cat that bobs at 4 Hz and a cat that vibrates into another dimension.&lt;/p&gt;


&lt;h3&gt;
  
  
  Challenge 3: The Camera Orbit
&lt;/h3&gt;

&lt;p&gt;Third-person camera in 3D needs two angles: &lt;strong&gt;yaw&lt;/strong&gt; (horizontal rotation around the player) and &lt;strong&gt;pitch&lt;/strong&gt; (vertical tilt). Converting those spherical coordinates to a Cartesian camera position is one of those formulas you derive, get wrong, stare at, re-derive:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CAM_DIST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;7.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;camYaw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// starts behind player, facing −Z toward plaza&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camYaw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camPitch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;CAM_DIST&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camYaw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camPitch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;CAM_DIST&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1.4&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camPitch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;CAM_DIST&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cz&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lookAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;1.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;Math.cos(camPitch)&lt;/code&gt; factor collapses the horizontal offset as pitch increases — when you're looking straight down, the camera is directly above. The &lt;code&gt;Math.sin(camPitch) * CAM_DIST&lt;/code&gt; lifts the camera vertically as you tilt up. Both terms together trace a sphere of radius &lt;code&gt;CAM_DIST&lt;/code&gt; centred on the player.&lt;/p&gt;

&lt;p&gt;Then the movement system has to use that same yaw to map WASD onto world directions, so pressing W always means "forward relative to where the camera is looking":&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camYaw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;fwd&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camYaw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;strafe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camYaw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;fwd&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camYaw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;strafe&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;atan2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;wx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;wz&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In 2D this is trivial. In 3D, getting the minus signs right between camera orbit and player movement — so that pressing D strafes right relative to the camera, not world-right — takes real attention.&lt;/p&gt;


&lt;h3&gt;
  
  
  Challenge 4: Collision Detection Across Rotated Space
&lt;/h3&gt;

&lt;p&gt;Two types of colliders in the world: &lt;strong&gt;circular&lt;/strong&gt; (trees, lamp posts, well, NPCs) and &lt;strong&gt;oriented box&lt;/strong&gt; (rotated houses). Circular collision is manageable:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;_resolveCircle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dz&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;dz&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;minDist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerRadius&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;minDist&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;dist&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dist&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="nx"&gt;minDist&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dz&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dist&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="nx"&gt;minDist&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dist&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Box colliders for houses are the full 3D problem. Each house is rotated to face the plaza — so the box's axes aren't aligned with the world. You can't just compare world-space coordinates. You have to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Transform the player into the house's local coordinate space&lt;/li&gt;
&lt;li&gt;Find the closest point on the axis-aligned box &lt;em&gt;in local space&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Compute the penetration depth&lt;/li&gt;
&lt;li&gt;Transform the push vector back to world space
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;_resolveBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotY&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;sin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cz&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// step 1: rotate into box local space&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cos&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;sin&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;dz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sin&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;dx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;cos&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;dz&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// step 2: nearest point on box surface&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;px&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lx&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lz&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lx&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;oz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lz&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;pz&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ox&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ox&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;oz&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;oz&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;playerRadius&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ox&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;oz&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;push&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerRadius&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// step 3: rotate push back to world space&lt;/span&gt;
    &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cos&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;nx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;sin&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;nz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;sin&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;nx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;cos&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;nz&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;push&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Fourteen lines. Two full rotation transforms. This took longer to get right than any other system in the game — and it's the kind of thing you genuinely cannot debug by guessing. You have to understand the coordinate space transform or you'll never know which of the four signs is wrong.&lt;/p&gt;


&lt;h3&gt;
  
  
  Challenge 5: Dawn as a Single Variable
&lt;/h3&gt;

&lt;p&gt;The whole sky — background colour, sun height, moon opacity, fog, ambient light, directional light — is driven by one number: &lt;code&gt;dawnAmount&lt;/code&gt;, a float from 0 (full night) to 1 (full dawn). This is how you avoid a lighting system that becomes unmanageable. One float. Every system reads it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Sky background lerp&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;night&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x0c1130&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dawn&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x3a4a82&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;scene&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lerp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;night&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;lerp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dawn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dawnAmount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;smoothing&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Sun rises from underground to sky&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sunY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dawnAmount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;62&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// -12 to +50 units&lt;/span&gt;
&lt;span class="nx"&gt;sunMesh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sunY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;sunMesh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;visible&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sunY&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Moon fades as sun rises&lt;/span&gt;
&lt;span class="nx"&gt;moonMesh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;material&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;opacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dawnAmount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;2.2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Scene lighting scales with dawn&lt;/span&gt;
&lt;span class="nx"&gt;sunLight&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intensity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.35&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dawnAmount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;hemi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intensity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dawnAmount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The sun colour shifts from orange to yellow at 40% dawn — mimicking the red horizon of early sunrise shifting to the cleaner yellow of morning:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;sunMesh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;material&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dawnAmount&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mh"&gt;0xff9940&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;0xffe680&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The six wisps scattered around the village each add 8% dawn when collected — a reward for exploration that makes the world respond to curiosity before the main quest requires it. Each wisp also shifts the lantern to its own colour (teal, blue, green) so the light you carry looks different depending on where you've been.&lt;/p&gt;


&lt;h3&gt;
  
  
  Challenge 6: The Lantern as a Resource, Not a Flag
&lt;/h3&gt;

&lt;p&gt;The original design treated "carrying light" as a binary state — you either had it or you didn't. That worked mechanically, but it meant every trip from the brazier to a home was identical. No tension, no urgency.&lt;/p&gt;

&lt;p&gt;The fix was turning the lantern into a fuel system. Light gathered at the brazier fills a &lt;code&gt;lanternFuel&lt;/code&gt; float to 1.0. It drains at roughly 1/85th per second — enough for two or three homes per trip at walking pace. As it drains, the lantern physically dims: intensity and opacity both scale with fuel level. The HUD tracks it with colour: gold when full, orange past the halfway point, red and labelled "almost out!" below 20%.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Each frame while carrying:&lt;/span&gt;
&lt;span class="nx"&gt;lanternFuel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lanternFuel&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;85&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lanLight&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;intensity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.8&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;lanternFuel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lanMesh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;material&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;opacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.95&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;lanternFuel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lanternFuel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;_clearLantern&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;SV&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The light faded — return to the brazier&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The brazier itself now reacts to how much of the village you've lit. Its flame scales up ~90% in size by full dawn, and its point light gets 70% brighter. The first time you come back to refill and notice the brazier has grown, it feels like the village is waking up with you.&lt;/p&gt;


&lt;h2&gt;
  
  
  Everything That Made the World Feel Alive
&lt;/h2&gt;

&lt;p&gt;On top of the core systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;28 fireflies&lt;/strong&gt; drifting on parametric Lissajous-style curves: &lt;code&gt;x = ox + sin(t × speed) × rx&lt;/code&gt;, &lt;code&gt;z = oz + cos(t × 1.3) × rz&lt;/code&gt; — the asymmetric frequencies mean they never loop in a straight line&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Occasional shooting stars&lt;/strong&gt; that spawn at a random point on the sky sphere, trail five fading ghost spheres, animate with &lt;code&gt;requestAnimationFrame&lt;/code&gt;, and clean themselves from the scene after 1.2 seconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aurora band&lt;/strong&gt; — 12 semi-transparent planes arranged in a ring at radius 70, each tilted slightly differently for an irregular shimmer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1,200 star particles&lt;/strong&gt; in a single &lt;code&gt;BufferGeometry&lt;/code&gt; draw call&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Particle burst system&lt;/strong&gt; — pool of sphere meshes with velocity and gravity, fading by life fraction, spawned on house lighting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chimney smoke&lt;/strong&gt; — every lit home emits slow expanding grey spheres from its chimney top every 0.75 seconds, growing as they rise and fading out, making lit homes visible from across the village&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bell on house lighting&lt;/strong&gt; — a deep resonant bell rings (four harmonics: 110 Hz, 220 Hz, 440 Hz, 880 Hz, each with a 3.2-second exponential decay) underneath the chord stab, so lighting a home sounds like an event&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Footstep audio&lt;/strong&gt; — alternating low tones (78 Hz / 68 Hz) timed to walking pace via a step timer, faster when running. All Web Audio API, no sound files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web Audio API ambient drone&lt;/strong&gt; — five overlapping sine oscillators at 55 Hz, 82.4 Hz, 110 Hz, 164.8 Hz, and 220 Hz (a harmonic series), each with decreasing gain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Touch joystick&lt;/strong&gt; — thumb delta clamped to 46px radius, normalised to ±1, rotated through camera yaw before being applied to movement&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimap&lt;/strong&gt; — Canvas 2D drawn every frame: houses as 8×8px squares (dark until lit, gold with glow when lit), NPC positions as dots, player as a filled triangle rotated to match camera yaw&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;House interiors&lt;/strong&gt; — enter any lit home: a full room with ceiling beams, a hearth with animated flame cones, warm flickering point light, a table, a bookshelf, and a rug. Each keeper has a note left on the table — Ash's has a bread recipe, Tovar's has a watchman's log, Mira's has three letters of SOLSTICE written in binary&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NPC cross-references&lt;/strong&gt; — each keeper mentions another by name in their opening line, so the village feels like people who know each other rather than eight isolated quest-givers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NPC dawn gathering&lt;/strong&gt; — past 50% dawn, all eight keepers slowly walk toward the plaza and face the brazier. At full dawn they're clustered together in a silent celebration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cat follows you&lt;/strong&gt; — approach the cat and press E; it trails behind you for the rest of the game. The deer does the opposite: get within five units and it startles, flags a flee direction, and runs at four times its normal speed until you're ten units away&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standing stone reacts to progress&lt;/strong&gt; — at zero homes lit the stone is cold. Past four it glows. At all eight, the Turing inscription appears&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;8 unique NPCs&lt;/strong&gt; with different skin tones, hair styles, and dialogue arcs that change after their home is lit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tree sway&lt;/strong&gt; — rotation.z and rotation.x oscillating at slightly different frequencies per tree so they never move in sync&lt;/li&gt;
&lt;/ul&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/Aryakoste" rel="noopener noreferrer"&gt;
        Aryakoste
      &lt;/a&gt; / &lt;a href="https://github.com/Aryakoste/solsticeGame" rel="noopener noreferrer"&gt;
        solsticeGame
      &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;Solstice Village&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;A 3D exploration game built for the June Solstice. You are Sol, the courier. The longest night has fallen and every window in the village has gone dark. Gather light at the central brazier and carry it home to home until the sky turns gold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://aryakoste.github.io/solsticeGame/" rel="nofollow noopener noreferrer"&gt;Play it here →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;Talk to each of the 8 keepers to learn their story&lt;/li&gt;
&lt;li&gt;Gather light at the plaza brazier — your lantern holds ~85 seconds of flame&lt;/li&gt;
&lt;li&gt;Carry the light to dark homes and deliver it&lt;/li&gt;
&lt;li&gt;Watch &lt;code&gt;dawnAmount&lt;/code&gt; rise from 0 to 1 as the village lights up — every system in the game (sky colour, sun height, fog, moon fade, brazier size, NPC behaviour) is driven by this single float&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a second ending. Collect all six spirit wisps scattered around the village without lighting any homes, and the game takes a different path.&lt;/p&gt;




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

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

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Input&lt;/th&gt;

&lt;th&gt;Action&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;&lt;code&gt;W&lt;/code&gt;&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

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





&lt;h2&gt;
  
  
  Prize Category
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The Alan Turing Prize Category
&lt;/h2&gt;

&lt;p&gt;One of the NPCs, Mira the clockmaker, says this when you approach her dark house:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Every lit window is a 1, every dark one a 0. Light mine and we add a bit to the dawn."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's not just flavour text. At the top of the screen runs a &lt;strong&gt;binary strip&lt;/strong&gt; that displays the ASCII value of each letter in "SOLSTICE" — one letter per house you light. When Bell's house lights up, the strip fills in &lt;code&gt;01010011&lt;/code&gt; (S = 83). When Fen's lights up, it fills &lt;code&gt;01001111&lt;/code&gt; (O = 79). Eight houses. Eight letters. Eight bytes spelling out the word in light.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;S = 01010011
O = 01001111
L = 01001100
S = 01010011
T = 01010100
I = 01001001
C = 01000011
E = 01000101
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the secret grove at the northeast edge of the map, a standing stone reads:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Beneath the runes, a name: TURING. And below it — ones and zeros."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Binary as metaphor for light. Light as computation. Every dark window a zero waiting to be flipped.&lt;/p&gt;

&lt;h2&gt;
  
  
  Google AI in the Process
&lt;/h2&gt;

&lt;p&gt;Google AI Studio and Gemini were part of the development loop throughout — helping reason through Three.js's coordinate conventions, sanity-checking the spherical camera orbit math, and catching the milliseconds-to-seconds unit mismatch before it became a harder bug. When I described the NPC-facing problem, Gemini confirmed the camera-convention issue with &lt;code&gt;lookAt&lt;/code&gt; and helped verify the &lt;code&gt;atan2&lt;/code&gt; formula direction before I changed code. The kind of quick second opinion that saves an hour of trial and error at midnight.&lt;/p&gt;




&lt;h2&gt;
  
  
  Play It
&lt;/h2&gt;

&lt;p&gt;Works in any modern browser, desktop and mobile.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;WASD&lt;/code&gt; / left joystick — move&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Shift&lt;/code&gt; — run&lt;/li&gt;
&lt;li&gt;Click + drag, or touch the right side of the screen — rotate camera&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;E&lt;/code&gt; / Talk button — interact with NPCs, brazier, homes, wisps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find the secret grove in the northeast. Read the standing stone — it says something different depending on how many homes you've lit. Pet the cat. Let the deer startle away from you. Light all eight homes and watch the sky turn.&lt;/p&gt;

&lt;p&gt;Or don't light any of them. Collect all six wisps instead, and see what the night has to say.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The longest night ends. That's what the solstice is: not the absence of light, but the moment right before it comes back.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;code&gt;#gamedev&lt;/code&gt; &lt;code&gt;#javascript&lt;/code&gt; &lt;code&gt;#threejs&lt;/code&gt; &lt;code&gt;#webdev&lt;/code&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>gamechallenge</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>ClawCraft: Bringing a Full Visual Studio to OpenClaw 🛠️</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Sat, 25 Apr 2026 22:21:00 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/clawcraft-bringing-a-full-visual-studio-to-openclaw-1iem</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/clawcraft-bringing-a-full-visual-studio-to-openclaw-1iem</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.clauneck.workers.dev/challenges/openclaw-2026-04-16"&gt;OpenClaw Challenge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Building OpenClaw skills is an incredibly powerful way to automate workflows across messaging platforms. But let's be honest: managing them locally, writing YAML/JSON boilerplate, ensuring they are safe to run, and debugging failures without a proper environment can require more context-switching than we'd like.&lt;/p&gt;

&lt;p&gt;So, for this developer challenge, I set out to build &lt;strong&gt;ClawCraft&lt;/strong&gt;, a comprehensive local development environment and companion skill specifically designed for OpenClaw. &lt;/p&gt;

&lt;p&gt;ClawCraft isn't just a basic tool—it's a &lt;strong&gt;powerful Command Line Interface (CLI)&lt;/strong&gt;, a &lt;strong&gt;local web dashboard (Client UI)&lt;/strong&gt; running a Fastify backend server, and an &lt;strong&gt;OpenClaw Skill&lt;/strong&gt;. It allows you to build, scan, debug, and manage your skills without ever touching code—&lt;em&gt;unless you want to.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Aryakoste/ClawCraft" rel="noopener noreferrer"&gt;&lt;strong&gt;⭐ Check out the GitHub Repository here! ⭐&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎨 The Client UI: A Beautiful Local Dashboard
&lt;/h2&gt;

&lt;p&gt;First and foremost, ClawCraft launches a sleek, React-based web dashboard locally on your machine. This is your command center. &lt;/p&gt;

&lt;p&gt;Instead of messing around with local folders, strict syntax, and terminal logs, the Client UI gives you a visual overview of every OpenClaw skill you have installed, the ability to trigger API commands instantly, and access to all the core developer tools right from your browser. &lt;/p&gt;




&lt;h2&gt;
  
  
  🔥 Headline Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. 🏗️ Visual Skill Builder
&lt;/h3&gt;

&lt;p&gt;Why write boilerplate when you can just drag and drop? The intuitive Client UI uses &lt;code&gt;@dnd-kit&lt;/code&gt; to let you string together the logic of your OpenClaw skills visually. For power users who still want granular control over their code, there's a fully integrated Monaco code editor providing a rich, IDE-like fallback experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. 🤖 AI Skill Generation
&lt;/h3&gt;

&lt;p&gt;Have an idea but don't want to drag blocks or write code? Tell ClawCraft what you want! Powered by Anthropic and OpenAI SDKs directly in the backend, you can just type a natural language prompt (e.g., &lt;em&gt;"Make a skill to fetch top 3 hacker news articles"&lt;/em&gt;). The AI will scaffold the entire OpenClaw skill structure, parameters, and logic for you instantly.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. 🚨 Built-in Security Scanner with Trust Scores
&lt;/h3&gt;

&lt;p&gt;You shouldn't just run random skills you find online blindly on your system. ClawCraft includes an automatic security scanner that analyzes any external skill (via URL or name), scanning the implementation logic, and summarizing exactly &lt;em&gt;what&lt;/em&gt; it is attempting to do. &lt;br&gt;
The scanner returns a &lt;strong&gt;Trust Score&lt;/strong&gt; directly in the UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  ✅ &lt;strong&gt;Safe&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;  ⚠️ &lt;strong&gt;Review Required&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;  🚨 &lt;strong&gt;Dangerous&lt;/strong&gt; (Do not install!) &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  4. 🪲 Live Debugger
&lt;/h3&gt;

&lt;p&gt;Testing an OpenClaw skill but it's failing silently in Slack or Telegram? Launch the local debugger dashboard. ClawCraft lets you inspect variables, view the actual HTTP payloads, and trace exactly where the flow broke in real-time.&lt;/p&gt;


&lt;h2&gt;
  
  
  💻 The Command Line Interface (CLI)
&lt;/h2&gt;

&lt;p&gt;Prefer living in the terminal? You can control your entire OpenClaw setup using the native CLI. Under the hood, this uses &lt;code&gt;commander.js&lt;/code&gt; and provides beautifully formatted output. &lt;/p&gt;

&lt;p&gt;Here are the commands you have at your disposal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;clawcraft start [--port] [--no-open]&lt;/code&gt; - Starts the local Fastify backend and launches the React dashboard.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;clawcraft list&lt;/code&gt; - Lists all currently installed skills along with their security trust score badges.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;clawcraft generate &amp;lt;description&amp;gt;&lt;/code&gt; - Uses LLM integrations to immediately scaffold and format an entire SKILL.md file from a single sentence request.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;clawcraft scan [target]&lt;/code&gt; - Scans all local skills, or a specific skill by URL or name, for malicious patterns and returns the Trust Score and findings list.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;clawcraft install &amp;lt;url&amp;gt; [--force]&lt;/code&gt; - Scans an external repository and installs it securely. Prompts if it's considered dangerous unless &lt;code&gt;--force&lt;/code&gt; is used!&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;clawcraft fix &amp;lt;skillName&amp;gt;&lt;/code&gt; - Immediately opens the browser UI directly to the local debugger for the specified skill.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;clawcraft improve &amp;lt;skillName&amp;gt;&lt;/code&gt; - An automated AI flow that attempts to rewrite your skill with better guardrails, optimized permissions, and deterministic instructions, and prompts to save!&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;clawcraft config [get/set]&lt;/code&gt; - Read and modify the configuration such as adding API keys safely.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🤯 The Meta Feature: The ClawCraft OpenClaw Skill
&lt;/h2&gt;

&lt;p&gt;Yes, ClawCraft comes with its own native, companion OpenClaw skill (&lt;code&gt;clawcraft&lt;/code&gt; tag) within the repo! &lt;/p&gt;

&lt;p&gt;Once your local ClawCraft server is running, you can manage &lt;em&gt;your entire OpenClaw development environment&lt;/em&gt; directly from Slack, Discord, Whatsapp, or Telegram using slash commands. It's wildly satisfying to build OpenClaw skills &lt;em&gt;using&lt;/em&gt; an OpenClaw skill.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;/clawcraft build "get current bitcoin price"&lt;/code&gt; - Automatically opens your UI and uses AI to generate the skill for you! &lt;/li&gt;
&lt;li&gt;  &lt;code&gt;/clawcraft scan {skill-url}&lt;/code&gt; - Scans the repository for the Trust Score and reads it back to you right in the chat.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;/clawcraft list&lt;/code&gt; - Returns a list of all your installed skills.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;/clawcraft search "find templates"&lt;/code&gt; - Searches available community templates and installed skills.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;/clawcraft status&lt;/code&gt; - See how many times your skills have fired and the estimated time they've saved you!&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🛠️ Tech Stack &amp;amp; Architecture
&lt;/h2&gt;

&lt;p&gt;ClawCraft is structured as a modern JavaScript monorepo using npm workspaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Frontend (&lt;code&gt;packages/client&lt;/code&gt;)&lt;/strong&gt;: React 18, Vite, TailwindCSS for styling, &lt;code&gt;@dnd-kit&lt;/code&gt; for drag-and-drop visuals, and Monaco Editor. &lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Backend (&lt;code&gt;packages/server&lt;/code&gt;)&lt;/strong&gt;: A lightning-fast Fastify server providing the core OpenClaw system APIs.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;CLI Toolkit&lt;/strong&gt;: Powered by Commander.js and Chalk.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;AI integrations&lt;/strong&gt;: Native SDK integrations for both Anthropic and OpenAI logic generation.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🚀 Quick Start (Running from Source)
&lt;/h2&gt;

&lt;p&gt;ClawCraft is designed to be cloned and run directly from the source to give you absolute control over your local environment. Here is how you can spin everything up:&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;# 1. Clone the repository&lt;/span&gt;
git clone https://github.com/Aryakoste/ClawCraft.git
&lt;span class="nb"&gt;cd &lt;/span&gt;ClawCraft

&lt;span class="c"&gt;# 2. Install dependencies (This securely installs both client and server via npm workspaces)&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# 3. Start the application&lt;/span&gt;
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Running &lt;code&gt;npm run dev&lt;/code&gt; kicks off a script that concurrently boot up both the Fastify server on port 4000 and the Vite Client UI dashboard simultaneously!)&lt;/em&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Some Screenshots for UI
&lt;/h1&gt;

&lt;p&gt;Skill Generator&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.amazonaws.com%2Fuploads%2Farticles%2Ft1a9smzz7muzvoc4hsx0.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.amazonaws.com%2Fuploads%2Farticles%2Ft1a9smzz7muzvoc4hsx0.png" alt=" " width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Template Gallery&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.amazonaws.com%2Fuploads%2Farticles%2Few9muduvsiawguzbu1do.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.amazonaws.com%2Fuploads%2Farticles%2Few9muduvsiawguzbu1do.png" alt=" " width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Skill Debugger&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.amazonaws.com%2Fuploads%2Farticles%2F3l2up1r5cdf2algczz42.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.amazonaws.com%2Fuploads%2Farticles%2F3l2up1r5cdf2algczz42.png" alt=" " width="800" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Skill Composer&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.amazonaws.com%2Fuploads%2Farticles%2Feyktbuai5nr61lps9cwx.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.amazonaws.com%2Fuploads%2Farticles%2Feyktbuai5nr61lps9cwx.png" alt=" " width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Usage Tracker &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.amazonaws.com%2Fuploads%2Farticles%2Flmbyk3mnm4uskg05fheo.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.amazonaws.com%2Fuploads%2Farticles%2Flmbyk3mnm4uskg05fheo.png" alt=" " width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Configuring the AI
&lt;/h2&gt;

&lt;p&gt;ClawCraft's powerful generator (&lt;code&gt;clawcraft generate&lt;/code&gt; and &lt;code&gt;clawcraft improve&lt;/code&gt;) relies on an LLM to do the heavy lifting. You can configure it to use Anthropic, OpenAI, local Ollama endpoints, and more. &lt;/p&gt;

&lt;p&gt;Use the built-in CLI to easily securely set your keys and providers (saved locally to &lt;code&gt;~/.clawcraft/config.json&lt;/code&gt;):&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;# Set your core provider (anthropic, openai, ollama, openai-compat, openclaw)&lt;/span&gt;
clawcraft config &lt;span class="nb"&gt;set &lt;/span&gt;llmProvider anthropic

&lt;span class="c"&gt;# Provide your authentication key&lt;/span&gt;
clawcraft config &lt;span class="nb"&gt;set &lt;/span&gt;apiKey &lt;span class="s2"&gt;"sk-ant-xxxxxxxxxx"&lt;/span&gt;

&lt;span class="c"&gt;# Set your preferred model version (Defaults to sonnet!)&lt;/span&gt;
clawcraft config &lt;span class="nb"&gt;set &lt;/span&gt;model &lt;span class="s2"&gt;"claude-3-5-sonnet-20241022"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once configured, point your messaging app to the local dashboard (&lt;code&gt;http://localhost:4000&lt;/code&gt;), load up the &lt;code&gt;skill/&lt;/code&gt; directory, and start giving it slash commands! &lt;/p&gt;




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

&lt;p&gt;I loved exploring how endlessly hackable OpenClaw is during this challenge. My primary goal with ClawCraft was to significantly lower the barrier to entry for creating, auditing, and installing those skills. I firmly believe that making OpenClaw visual, secure, and easily manageable will help onboard a lot more non-developers into the AI automation space. &lt;/p&gt;

&lt;p&gt;Would love any thoughts, PRs, or feedback from the community! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Aryakoste/ClawCraft" rel="noopener noreferrer"&gt;Drop a ⭐ on the Repo or try it out!&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>openclawchallenge</category>
    </item>
    <item>
      <title>I Put Carbon Pledges on the Solana Blockchain for Earth Day (And Built the AI to Back It Up)</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Sun, 19 Apr 2026 20:00:48 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/i-put-carbon-pledges-on-the-solana-blockchain-for-earth-day-and-built-the-ai-to-back-it-up-2hin</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/i-put-carbon-pledges-on-the-solana-blockchain-for-earth-day-and-built-the-ai-to-back-it-up-2hin</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.clauneck.workers.dev/challenges/weekend-2026-04-16"&gt;Weekend Challenge: Earth Day Edition&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Did you know that a single cheeseburger emits roughly &lt;strong&gt;3.5 kg of CO₂&lt;/strong&gt;? That's equivalent to driving 14 km in a petrol car — from a &lt;em&gt;sandwich&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Most of us have no idea what our daily choices actually cost the planet. And even when we do, knowing isn't enough. What if you could &lt;em&gt;prove&lt;/em&gt; you're changing — publicly, permanently, on the blockchain?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EcoLens&lt;/strong&gt; is an AI-powered carbon footprint analyzer that goes beyond awareness. It identifies your impact, proposes greener alternatives, and lets you &lt;strong&gt;pledge your commitment on the Solana blockchain&lt;/strong&gt; — a public, immutable record that your word is real.&lt;/p&gt;




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

&lt;p&gt;Carbon footprint calculators exist, but they're tedious. You fill out a form, pick from dropdowns, hit calculate, and get a vague yearly number that means nothing to your Tuesday lunch decision.&lt;/p&gt;

&lt;p&gt;The real gap isn't information — it's &lt;em&gt;accountability&lt;/em&gt;. People know beef is carbon-heavy. They still order it. What changes behavior is a commitment with skin in the game.&lt;/p&gt;

&lt;p&gt;That's the loop I wanted to close: &lt;strong&gt;identify → understand → pledge → act&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What EcoLens Does
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📸 Vision Analysis
&lt;/h3&gt;

&lt;p&gt;Upload any image — your meal, a shopping receipt, your car, a product — and &lt;strong&gt;Gemini 2.0 Flash&lt;/strong&gt; analyzes it using real lifecycle emissions data. You don't describe anything; just point your camera.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✍️ Text &amp;amp; Voice Analysis
&lt;/h3&gt;

&lt;p&gt;Type or &lt;em&gt;speak&lt;/em&gt; a description:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"I flew economy class from Mumbai to London"&lt;/em&gt;&lt;br&gt;
→ &lt;strong&gt;1,850 kg CO₂&lt;/strong&gt; · Very High Impact · Equivalent to driving 7,400 km&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  ⚖️ Compare Mode
&lt;/h3&gt;

&lt;p&gt;Can't decide? Compare two options side by side — "beef burger vs. black bean burger" — and see exactly how many kg CO₂ you save by choosing the greener option, with a winner crown.&lt;/p&gt;

&lt;h3&gt;
  
  
  🌿 Structured Results
&lt;/h3&gt;

&lt;p&gt;Every analysis returns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CO₂ in kg, severity rating, animated breakdown by source&lt;/li&gt;
&lt;li&gt;3 specific, actionable alternatives with estimated savings&lt;/li&gt;
&lt;li&gt;A relatable real-world equivalent&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ◎ Solana On-Chain Pledges ← &lt;em&gt;the key differentiator&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;After every analysis, you can sign a pledge with your Phantom wallet. The commitment is written as a Memo transaction on Solana — permanent, public, tied to your wallet address.&lt;/p&gt;

&lt;h3&gt;
  
  
  🤖 Streaming AI Agent
&lt;/h3&gt;

&lt;p&gt;A persistent chat powered by Gemini that streams responses token-by-token, secured behind Auth0.&lt;/p&gt;

&lt;h3&gt;
  
  
  📊 Carbon Budget + History
&lt;/h3&gt;

&lt;p&gt;Set a weekly CO₂ budget. Every analysis is saved to localStorage, tracked against your goal, and visualised in a circular progress meter.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Choice&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Framework&lt;/td&gt;
&lt;td&gt;Next.js 15 (App Router)&lt;/td&gt;
&lt;td&gt;Server components + API routes in one repo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Google Gemini 2.0 Flash&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Vision + text + streaming, accurate emissions data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Auth0 for Agents&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Protects AI endpoints, user identity scoping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blockchain&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Solana (Devnet)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;On-chain pledge via Phantom + Memo Program&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Animation&lt;/td&gt;
&lt;td&gt;Framer Motion&lt;/td&gt;
&lt;td&gt;Smooth result reveals, animated CO₂ bars&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Styling&lt;/td&gt;
&lt;td&gt;Tailwind CSS&lt;/td&gt;
&lt;td&gt;Custom dark earth-tone design system&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  How I Used Google Gemini
&lt;/h2&gt;

&lt;p&gt;Gemini is the brain of EcoLens — it handles both image analysis and chat via &lt;code&gt;gemini-2.0-flash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The key insight was engineering a &lt;em&gt;structured output contract&lt;/em&gt;. The model always returns valid JSON so the UI can render rich cards without parsing gymnastics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ANALYSIS_PROMPT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`You are EcoLens AI, an expert environmental scientist.
Analyze the input and return ONLY valid JSON:
{
  "carbonKg": number,
  "category": "food" | "transport" | "energy" | "shopping" | "waste" | "other",
  "title": string,
  "summary": string,
  "breakdown": [{"label": string, "kg": number, "percentage": number}],
  "alternatives": [{"action": string, "impact": string, "reduction": string}],
  "equivalent": string,
  "severity": "low" | "medium" | "high" | "very_high",
  "rating": number
}`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For image analysis, the image and prompt go in a single multimodal API call:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Part&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;inlineData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;imageBase64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;mimeType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&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="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Analyze the carbon footprint of everything in this image.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateContent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parts&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="na"&gt;generationConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// low temp = consistent scientific estimates&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The AI chat uses &lt;strong&gt;streaming&lt;/strong&gt; via &lt;code&gt;sendMessageStream&lt;/code&gt; — responses type out token-by-token with a blinking cursor, making it feel alive:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;streamChatWithEcoAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessageStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stream&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The API route pipes this directly into a &lt;code&gt;ReadableStream&lt;/code&gt; response — no buffering, no delay.&lt;/p&gt;


&lt;h2&gt;
  
  
  How I Used Auth0 for Agents
&lt;/h2&gt;

&lt;p&gt;Every call that touches the Gemini AI is &lt;strong&gt;gated by Auth0&lt;/strong&gt; before the agent acts. This is the "Auth0 for Agents" pattern: the AI doesn't act anonymously, it acts &lt;em&gt;on behalf of&lt;/em&gt; a verified identity.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/api/analyze/route.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getSession&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authentication required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Agent acts on behalf of session.user.sub — traceable, auditable&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;analyzeCarbon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageBase64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;imageMimeType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;analyzedBy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sub&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The same gate protects &lt;code&gt;/api/chat&lt;/code&gt; and &lt;code&gt;/api/compare&lt;/code&gt;. No anonymous AI calls — every analysis is tied to a real, verified person.&lt;/p&gt;


&lt;h2&gt;
  
  
  How I Used Solana — The Heart of the Accountability Loop
&lt;/h2&gt;

&lt;p&gt;This is the part I'm most excited about, and the piece that makes EcoLens more than just another carbon calculator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The idea:&lt;/strong&gt; awareness without commitment changes nothing. Solana lets us make commitments &lt;em&gt;permanent and public&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Gemini analyzes your activity and suggests a greener alternative&lt;/li&gt;
&lt;li&gt;You click &lt;strong&gt;"Sign pledge with Phantom"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;EcoLens constructs a Memo transaction encoding your pledge, the CO₂ saved, and a timestamp&lt;/li&gt;
&lt;li&gt;Phantom signs and broadcasts it to Solana Devnet&lt;/li&gt;
&lt;li&gt;The transaction is confirmed on-chain — your pledge is now permanent
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;TransactionInstruction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;clusterApiUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@solana/web3.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MEMO_PROGRAM_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PublicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;memoData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;EcoLens&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pledge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I pledge to: cycle instead of drive this week&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;carbonKg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TransactionInstruction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;pubkey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isSigner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isWritable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;programId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MEMO_PROGRAM_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;memoData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;solana&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signAndSendTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;confirmTransaction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;blockhash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastValidBlockHeight&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The pledge is verifiable on &lt;a href="https://explorer.solana.com/?cluster=devnet" rel="noopener noreferrer"&gt;Solana Explorer&lt;/a&gt;. Anyone can look up your wallet and see your carbon commitments, timestamped and immutable.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why the Memo Program?
&lt;/h3&gt;

&lt;p&gt;The Solana Memo Program (&lt;code&gt;MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr&lt;/code&gt;) is the simplest, cheapest way to write arbitrary data on-chain. A pledge transaction costs a fraction of a cent in SOL and is confirmed in ~400ms. It's perfect for this use case — lightweight, auditable, and human-readable.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why This Matters Beyond the Demo
&lt;/h3&gt;

&lt;p&gt;Carbon pledges have a trust problem. Corporate net-zero commitments get announced and quietly abandoned. There's no receipt. Solana changes that: your pledge is a transaction hash. It can't be edited, deleted, or denied. Future versions of EcoLens could build a public leaderboard of wallets with the most on-chain green commitments — turning individual accountability into social proof.&lt;/p&gt;


&lt;h2&gt;
  
  
  A Real Example: From Analysis to On-Chain Pledge
&lt;/h2&gt;

&lt;p&gt;Here's the full EcoLens loop in action:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. User uploads photo of beef steak dinner
   → Gemini Vision: 6.8 kg CO₂ · High Impact

2. Breakdown:
   Beef (production)    ████████  5.2 kg (76%)
   Cooking energy       ██        0.9 kg (13%)
   Transport/packaging  ▌         0.7 kg (11%)

3. Equivalent to: Driving 27 km in a petrol car

4. Top alternative: "Choose chicken instead — Save ~4.1 kg CO₂"

5. User clicks "Sign pledge with Phantom"
   → Phantom signs memo transaction
   → Confirmed on Solana Devnet in 412ms
   → TX: 3xK7...mNpQ (verifiable on Explorer)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's the full loop — from a photo to an on-chain commitment in under 30 seconds.&lt;/p&gt;


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

&lt;p&gt;&lt;strong&gt;Structured outputs unlock rich UIs.&lt;/strong&gt; Getting Gemini to reliably return JSON meant the frontend could be fully reactive — no parsing edge cases, no streaming text parsing hacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Temperature matters for science.&lt;/strong&gt; At &lt;code&gt;0.7&lt;/code&gt;, CO₂ estimates drift between calls. At &lt;code&gt;0.3&lt;/code&gt;, they're reproducible and match published lifecycle data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solana's Memo Program is criminally underused.&lt;/strong&gt; It's the simplest on-chain data primitive — 0.000005 SOL per transaction, confirmed in milliseconds, human-readable on Explorer. For any app that needs verifiable records, it's a better solution than most people realize.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auth-gating AI is a pattern, not an afterthought.&lt;/strong&gt; Making the AI agent require Auth0 session means every analysis is tied to a real identity — which is the foundation for future per-user carbon portfolios and wallet-linked pledge histories.&lt;/p&gt;


&lt;h2&gt;
  
  
  Try It Yourself
&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/Aryakoste" rel="noopener noreferrer"&gt;
        Aryakoste
      &lt;/a&gt; / &lt;a href="https://github.com/Aryakoste/ecolens" rel="noopener noreferrer"&gt;
        ecolens
      &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;🌍 EcoLens&lt;/h1&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AI Carbon Footprint Analyzer with On-Chain Pledges&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://nextjs.org" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8e285d6c04022c2a7b4d9c10ab4261dae0236525c30a21caddeb90740d2294bb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e6578742e6a732d31352d626c61636b3f6c6f676f3d6e6578742e6a73" alt="Next.js"&gt;&lt;/a&gt;
&lt;a href="https://ai.google.dev" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/3fb5c70ab6db43703e7a1f98d1555981d1166fcf47ed261d8bdc01d32af52a76/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f476f6f676c655f47656d696e692d322e305f466c6173682d3432383546343f6c6f676f3d676f6f676c65" alt="Gemini"&gt;&lt;/a&gt;
&lt;a href="https://auth0.com" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/3bd7a062d6075189dde3785510450d819b81428b3866dfbc2fb4ce3bcc0aede6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f41757468302d666f725f4167656e74732d4542353432343f6c6f676f3d6175746830" alt="Auth0"&gt;&lt;/a&gt;
&lt;a href="https://solana.com" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/725e797738a16ebc201de5bd28fc1a4d540b7f075619ff43324cc41cba544fc0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f536f6c616e612d4465766e65742d3939343546463f6c6f676f3d736f6c616e61" alt="Solana"&gt;&lt;/a&gt;
&lt;a href="https://typescriptlang.org" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/dcff4370c2726b105ada0a3b8a05b83517edd4f9e79215ce2172214b26bc4a5b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f547970655363726970742d352d3331373843363f6c6f676f3d74797065736372697074" alt="TypeScript"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Snap a photo of your lunch, describe your commute, or upload a receipt — EcoLens uses &lt;strong&gt;Google Gemini Vision&lt;/strong&gt; to instantly reveal the hidden CO₂ cost of your daily choices. Then &lt;strong&gt;pledge to do better on the Solana blockchain&lt;/strong&gt; — a permanent, public, verifiable commitment.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;✨ Features&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;Feature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;📸 &lt;strong&gt;Vision Analysis&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Upload any photo — Gemini Vision identifies items and calculates CO₂&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✍️ &lt;strong&gt;Text Analysis&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Describe any activity and get an accurate, sourced emission estimate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🎙️ &lt;strong&gt;Voice Input&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Speak your description using the browser's Speech API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚖️ &lt;strong&gt;Compare Mode&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Race two options side by side — see the greener choice with a winner crown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;◎ &lt;strong&gt;Solana Pledges&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Sign an on-chain pledge with Phantom — permanent, immutable, verifiable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🤖 &lt;strong&gt;Streaming AI Chat&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Gemini-powered eco-agent that streams responses token-by-token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📊 &lt;strong&gt;Carbon Budget&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Set a weekly CO₂ goal and track it against a&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/Aryakoste/ecolens" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/aryakoste/ecolens
&lt;span class="nb"&gt;cd &lt;/span&gt;ecolens
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.local.example .env.local
&lt;span class="c"&gt;# Add GEMINI_API_KEY, Auth0 credentials&lt;/span&gt;
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test the Solana pledge feature, install &lt;a href="https://phantom.app" rel="noopener noreferrer"&gt;Phantom wallet&lt;/a&gt; and switch it to &lt;strong&gt;Devnet&lt;/strong&gt; in settings.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;[ ] &lt;strong&gt;Mainnet pledges&lt;/strong&gt; — real SOL-backed carbon commitments with token rewards for follow-through&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Public pledge leaderboard&lt;/strong&gt; — on-chain wallet rankings for green commitments&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;NFT certificates&lt;/strong&gt; — mint a Solana NFT when you hit a weekly carbon goal&lt;/li&gt;
&lt;li&gt;[ ] &lt;strong&gt;Snowflake analytics&lt;/strong&gt; — aggregate anonymized emissions data across all users for community insights&lt;/li&gt;
&lt;/ul&gt;




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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prize&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;How it's used&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best use of Solana&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;@solana/web3.js&lt;/code&gt; + Phantom&lt;/td&gt;
&lt;td&gt;On-chain carbon pledges via the Memo Program&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best use of Google Gemini&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Gemini 2.0 Flash&lt;/td&gt;
&lt;td&gt;Vision analysis, structured JSON output, streaming chat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best use of Auth0 for Agents&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;@auth0/nextjs-auth0&lt;/code&gt; v3&lt;/td&gt;
&lt;td&gt;Auth-gates every AI endpoint — the agent acts on behalf of a verified identity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Every gram of CO₂ you avoid is a gift to the planet. And now, you can prove it. Happy Earth Day 🌍&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built with Google Gemini 2.0 Flash, Auth0 for Agents, and Solana for the DEV.to Earth Day Challenge 2025.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>solana</category>
    </item>
    <item>
      <title>I Built a Government-Grade Button Clicking Certification Program (Because the World Needs It)</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Tue, 07 Apr 2026 16:47:36 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/i-built-a-government-grade-button-clicking-certification-program-because-the-world-needs-it-3j82</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/i-built-a-government-grade-button-clicking-certification-program-because-the-world-needs-it-3j82</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.clauneck.workers.dev/challenges/aprilfools-2026"&gt;DEV April Fools Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚠️ NATIONAL CLICK THREAT LEVEL: ELEVATED
&lt;/h2&gt;

&lt;p&gt;Let me ask you something.&lt;/p&gt;

&lt;p&gt;You use buttons every day. Login buttons. Submit buttons. "Accept all cookies" buttons (without reading a single word). Elevator buttons. Crosswalk buttons that don't actually do anything.&lt;/p&gt;

&lt;p&gt;But have you ever been &lt;em&gt;certified&lt;/em&gt; to click those buttons?&lt;/p&gt;

&lt;p&gt;No. You haven't. And frankly, it's reckless.&lt;/p&gt;

&lt;p&gt;That's why I built the &lt;strong&gt;International Bureau of Button Clicking Certification (IBCC)&lt;/strong&gt; — a fully interactive, deeply useless, government-bureaucracy-themed web application that puts you through six increasingly absurd examinations to determine if you are, in fact, qualified to press a rectangular area on an illuminated screen.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏛️ Why Button Clicking Certification Matters in 2026
&lt;/h2&gt;

&lt;p&gt;Let's look at the facts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The average knowledge worker clicks &lt;strong&gt;4,217 times per day&lt;/strong&gt;. That's over &lt;strong&gt;1.5 million clicks per year&lt;/strong&gt; — completely unregulated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero countries&lt;/strong&gt; currently require a clicking license. Zero. Not even Switzerland, and they regulate &lt;em&gt;everything&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;In 1987, a single misclick at the Pentagon accidentally ordered &lt;strong&gt;40,000 rubber ducks&lt;/strong&gt;. This is not in any official record because they covered it up. But I believe it happened.&lt;/li&gt;
&lt;li&gt;Self-driving cars are regulated. Surgeons are licensed. Barbers need a certificate. But the person clicking "Deploy to Production" on a Friday at 4:59 PM? No credentials required. &lt;em&gt;Think about that.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The click economy is booming. AI is automating everything &lt;em&gt;except&lt;/em&gt; clicking. If anything, we need &lt;strong&gt;more&lt;/strong&gt; human clickers than ever. And yet, the industry has no standards, no oversight, and no governing body.&lt;/p&gt;

&lt;p&gt;Until now.&lt;/p&gt;

&lt;p&gt;The IBCC was established in 1847 (citation needed) and has been monitoring global click activity from a basement somewhere ever since.&lt;/p&gt;




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

&lt;p&gt;A single-page HTML/CSS/JS application that is equal parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DMV waiting room&lt;/strong&gt; (the aesthetic)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escape room&lt;/strong&gt; (the challenges)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fever dream&lt;/strong&gt; (the experience)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Core Experience
&lt;/h3&gt;

&lt;p&gt;You land on the page and you're greeted by an official government seal, a scrolling threat-level ticker, and a giant 3D red button that is begging to be pressed.&lt;/p&gt;

&lt;p&gt;Every click is tracked. Every click is logged. Every click brings you closer to certification — or further from sanity.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Stats Dashboard
&lt;/h3&gt;

&lt;p&gt;Because no government bureau is complete without meaningless metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Total Clicks&lt;/strong&gt; — the only number that matters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clicks Per Second&lt;/strong&gt; — your raw throughput&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accuracy™&lt;/strong&gt; — a completely fabricated percentage that goes up the more you click, because we believe in positive reinforcement&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click Power&lt;/strong&gt; — a multiplier that grows every 100 clicks, achieving absolutely nothing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Clearance Level System
&lt;/h3&gt;

&lt;p&gt;As you click, you ascend through increasingly dramatic security clearances:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Clicks&lt;/th&gt;
&lt;th&gt;Clearance Level&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;UNCLASSIFIED&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;CONFIDENTIAL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;SECRET&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;150&lt;/td&gt;
&lt;td&gt;TOP SECRET&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;COSMIC TOP SECRET&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;800&lt;/td&gt;
&lt;td&gt;ULTRA MEGA SECRET&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,500&lt;/td&gt;
&lt;td&gt;BEYOND CLASSIFICATION&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3,000&lt;/td&gt;
&lt;td&gt;CLICK DEITY&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each level has its own color, its own glow, and its own sense of hollow accomplishment.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Six Certification Examinations
&lt;/h3&gt;

&lt;p&gt;This is where it gets &lt;em&gt;interactive&lt;/em&gt;. Each exam unlocks at a certain click threshold and tests a completely useless skill:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EXAM 1: Speed Clicking Qualification&lt;/strong&gt;&lt;br&gt;
Click 20 times in 5 seconds. Prove you are not, in fact, a sloth. This is your warm-up. If you fail this, the Bureau recommends a different career path (perhaps data entry, where the stakes are somehow even lower).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EXAM 2: Precision Click Assessment&lt;/strong&gt;&lt;br&gt;
Five targets appear on screen. They shrink. You must hit them. Missing is described as "a federal offense" in the fine print (it isn't, but the guilt is real). The targets get smaller with each hit because the Bureau believes in escalating psychological pressure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EXAM 3: Patience Endurance Trial&lt;/strong&gt;&lt;br&gt;
Hold a button for &lt;em&gt;exactly&lt;/em&gt; 7.0 seconds. Not 6.5. Not 7.8. Seven. There's a ±0.5 second tolerance because the Bureau is generous (they aren't, but the lawyers insisted). This exam has a 73% failure rate among developers because we are physically incapable of waiting for anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EXAM 4: Rhythmic Click Synchronization&lt;/strong&gt;&lt;br&gt;
A circle pulses. You click when it lights up. It's like Guitar Hero but with a single button, no music, and no fun. Score 6 out of 10 to pass. The Bureau considers anything below that "arrhythmic clicking" which is, apparently, a diagnosable condition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EXAM 5: Morse Code Transmission&lt;/strong&gt;&lt;br&gt;
Tap out S.O.S. in Morse code (short-short-short, long-long-long, short-short-short). This is the exam where most people realize they have no idea what Morse code actually is, despite confidently claiming otherwise at dinner parties.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EXAM 6: The Trust Exercise&lt;/strong&gt;&lt;br&gt;
This is my favorite. A big red button appears. It says "DON'T CLICK." You must resist for 10 seconds. While the system actively taunts you:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Come on, just one little click..."&lt;br&gt;
"Nobody's watching... 👀"&lt;br&gt;
"Your finger is already moving, isn't it?"&lt;br&gt;
"Other test subjects all failed at this point..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you click it, a giant "DENIED" stamp slams across your screen. You deserve it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bonus Chaos
&lt;/h3&gt;

&lt;p&gt;Because six exams weren't enough:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Combo System&lt;/strong&gt;: Click fast enough and a combo counter appears. Hit 20x for the "UNSTOPPABLE" achievement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;13+ Achievements&lt;/strong&gt;: From "First Click" (participation trophy energy) to "CERTIFIED CLICKER" (you completed all exams and should probably go outside).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Random Events&lt;/strong&gt;: A 3% chance per click that the system flags you with alerts like "SUSPICIOUS CLICKING PATTERN DETECTED" or "Agent #404 is now monitoring this session."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The DENIED Stamp&lt;/strong&gt;: Randomly slams across your screen with a satisfying animation, just to keep you on your toes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Particle Explosions&lt;/strong&gt;: Every click spawns emoji particles. Higher combos = more particles. Your screen will look like a New Year's Eve celebration at a bureaucratic office party.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confetti&lt;/strong&gt;: At every milestone (10, 50, 100, 500, 1000 clicks), confetti rains down. Because positive reinforcement is free.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secret Keyboard Shortcuts&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;D&lt;/strong&gt; — Activates Dance Mode (the entire page starts shifting through hue rotations while the button spins maniacally)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;T&lt;/strong&gt; — Thermal Vision (high saturation + contrast, makes the button look like a heat signature)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S&lt;/strong&gt; — Secret bonus: awards 50 clicks instantly and fires confetti&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Certificate
&lt;/h3&gt;

&lt;p&gt;Complete all six exams and you receive an official &lt;strong&gt;Certificate of Completion&lt;/strong&gt; — a parchment-textured, gold-bordered, absolutely meaningless document that declares you a "Certified Professional Button Clicker (CPBC)."&lt;/p&gt;

&lt;p&gt;It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your name (you get to type it in, very official)&lt;/li&gt;
&lt;li&gt;A 3D rotating trophy&lt;/li&gt;
&lt;li&gt;A stamp in the corner that reads "VERIFIED USELESS"&lt;/li&gt;
&lt;li&gt;A statement that the certificate "carries absolutely no legal weight in any jurisdiction, real or imagined"&lt;/li&gt;
&lt;li&gt;A note that it's valid for &lt;strong&gt;0 days&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ Technical Decisions (and Regrets)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pure HTML/CSS/JS.&lt;/strong&gt; No frameworks. No build tools. No npm install. Just one file and vibes. If a government bureau from 1847 could build a website, they wouldn't use React either.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSS 3D transforms&lt;/strong&gt; for the button (it has actual depth with a &lt;code&gt;translateZ&lt;/code&gt; based top and side), the trophy rotation, and the certificate reveal animation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pure CSS animations&lt;/strong&gt; everywhere — the scanning ticker, the seal rotation, the shimmer on progress bars, the particle system, the combo pop, the stamp slam. Sixty percent of the code is CSS, which feels appropriate for something that accomplishes nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No external dependencies.&lt;/strong&gt; Just Google Fonts. The Bureau doesn't trust third-party packages (honestly, neither should you).&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 Google AI: The Bureau's Secret Intelligence Division
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Gemini for Ideation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Honestly, half the challenge ideas came from brainstorming with Gemini. I started with "speed clicking test" and asked it to push the absurdity further. The Morse Code SOS exam and the Trust Exercise (where you have to NOT click a button for 10 seconds) were both born from those conversations. Gemini is genuinely great at "yes, and" — give it a silly premise and it will escalate it with you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Gemini Specifically&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a project this stupid, I needed an AI that could commit fully to the bit without constantly trying to be helpful or breaking character with disclaimers. Gemini handled the deadpan tone better than I expected — it never once tried to inform me that button clicking certification isn't real, which I respect deeply.&lt;/p&gt;

&lt;p&gt;I also used Gemini to help workshop the bureaucratic tone — the fake fun facts, the threat-level ticker messages, the achievement names. When you need 12 variations of "fake government propaganda about clicking," an AI is genuinely the right tool for the job.&lt;/p&gt;

&lt;p&gt;What surprised me: Gemini was &lt;em&gt;really&lt;/em&gt; good at the deadpan humor. I expected it to play things safe, but when I told it to commit fully to the bit and write like a 1980s instruction manual that had lost its mind, it delivered.&lt;/p&gt;




&lt;h2&gt;
  
  
  📋 Form CL-7042: Closing Remarks
&lt;/h2&gt;

&lt;p&gt;Look, I know what you're thinking: &lt;em&gt;"This is completely useless."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Yes. That's the point. That's literally the challenge.&lt;/p&gt;

&lt;p&gt;But also — is it? In a world where we click "I have read and agree to the Terms of Service" without reading a single word, maybe we &lt;em&gt;do&lt;/em&gt; need a certification program. Maybe we &lt;em&gt;should&lt;/em&gt; be tested. Maybe the fact that anyone can deploy to production with a single, untrained, uncertified click is the real problem.&lt;/p&gt;

&lt;p&gt;Or maybe I just spent way too long making a 3D button that shoots emoji particles.&lt;/p&gt;

&lt;p&gt;Either way, I regret nothing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go get certified&lt;/strong&gt;: &lt;a href="https://aryakoste.github.io/buttonClickingCertification/button-certification.html" rel="noopener noreferrer"&gt;https://aryakoste.github.io/buttonClickingCertification/button-certification.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The International Bureau of Button Clicking Certification. Est. 1847. "Click Responsibly."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;P.S. — Your clicks are being monitored. They always have been.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built for the DEV Challenge: Build Something Useless. This software solves exactly zero real-world problems and I'm proud of it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>418challenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I Gave My Notion Workspace a Brain — Here's What Happened</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Sun, 29 Mar 2026 19:43:20 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/i-gave-my-notion-workspace-a-brain-heres-what-happened-3ehp</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/i-gave-my-notion-workspace-a-brain-heres-what-happened-3ehp</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.clauneck.workers.dev/challenges/notion-2026-03-04"&gt;Notion MCP Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I spent a weekend building an AI that autonomously operates inside Notion. You type one sentence. It searches your workspace, reasons about what to do, creates pages, spins up databases, populates tasks — and you watch every single step happen in real time. Here's how I built it and why it might be the most useful thing I've ever made.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Frustration That Started This
&lt;/h2&gt;

&lt;p&gt;I've been a Notion user. My workspace is a sprawling mess of half-finished project pages, meeting notes that never got followed up on, and goals I set in January that I haven't looked at since.&lt;/p&gt;

&lt;p&gt;The problem isn't Notion. Notion is incredible. The problem is that &lt;strong&gt;Notion is entirely passive&lt;/strong&gt;. It sits there, waiting. It does nothing unless you tell it exactly what to do, how to structure it, and where to put it.&lt;/p&gt;

&lt;p&gt;I kept thinking: what if Notion could just... &lt;em&gt;think&lt;/em&gt;? What if I could say "set up a Q2 OKR tracking system" and it would actually &lt;em&gt;do&lt;/em&gt; it — build the database, create the objectives, set up the weekly check-in templates, write the guidelines page — without me having to architect every single piece?&lt;/p&gt;

&lt;p&gt;That's Apex.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;Apex&lt;/strong&gt; is a full-stack AI command center that gives &lt;strong&gt;Llama 3.3 70B (via Groq)&lt;/strong&gt; complete autonomous access to your Notion workspace. You chat with it naturally. It reasons, plans, and executes — using 10 Notion MCP tools in sequence — while you watch every operation happen live on screen.&lt;/p&gt;

&lt;p&gt;It's not a chatbot that tells you &lt;em&gt;how&lt;/em&gt; to use Notion. It's an agent that &lt;em&gt;uses&lt;/em&gt; Notion for you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why Groq?&lt;/strong&gt; Groq's free tier gives you 14,400 requests/day with no credit card required. Llama 3.3 70B handles tool calling excellently — and it's genuinely fast. Zero cost to run.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  7 Intelligent Modes
&lt;/h3&gt;

&lt;p&gt;Each mode has a deeply engineered system prompt that makes the AI behave like a domain specialist:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;💬 &lt;strong&gt;Chat&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Natural language Q&amp;amp;A — ask anything about your workspace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🏗️ &lt;strong&gt;Project Blueprint&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;One sentence → hub page + task database + timeline + risk log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🧠 &lt;strong&gt;Brain Dump&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Raw chaos → organized, searchable Notion knowledge base&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📋 &lt;strong&gt;Meeting Intelligence&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Paste notes → decisions, action items, owners, follow-ups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📊 &lt;strong&gt;Weekly Review&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;AI scans entire workspace → CEO-level intelligence report&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🎯 &lt;strong&gt;OKR Tracker&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Define goals → complete OKR system with check-in templates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📅 &lt;strong&gt;Content Calendar&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Describe strategy → 20+ content ideas across all channels&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  The Feature I'm Most Proud Of: Live Tool Use Visualization
&lt;/h2&gt;

&lt;p&gt;Most AI tools are black boxes. You ask, you wait, you get an answer. You have no idea what happened in between.&lt;/p&gt;

&lt;p&gt;Apex flips this. As the AI works, you see every single Notion operation as it happens — animated cards streaming in, showing you exactly what the AI is doing and why:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🌐  Scanning Workspace...                          ✓ 12 pages, 3 databases
🔍  Searching Notion...     "Q2 goals"             ✓ Found 2 related pages
📄  Creating Page...        "🎯 Q2 Goals Hub"      ✓ Created
🗄️  Building OKR Database.. "Q2 OKR Tracker"       ✓ Created with 8 fields
➕  Adding Record...        "Grow MRR by 40%"      ✓ Objective added
➕  Adding Record...        "Key Result: MRR &amp;gt; $50k"✓ KR added
📄  Creating Page...        "📋 Weekly Check-in"   ✓ Template created
📄  Creating Page...        "🏆 Wins &amp;amp; Learnings"  ✓ Log created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eight Notion operations, chained intelligently, executed autonomously. The whole OKR system is live in your workspace before you've finished reading the output.&lt;/p&gt;

&lt;p&gt;This transparency is what makes it feel like a genuine AI colleague rather than a magic trick.&lt;/p&gt;




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

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/VbVeDkHg6tQ"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical Deep Dive
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Next.js 14 (App Router) + TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling&lt;/strong&gt;: Tailwind CSS with glassmorphism, animated ambient orbs, dot-grid background&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI&lt;/strong&gt;: Llama 3.3 70B via Groq SDK — streaming + multi-turn tool use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notion&lt;/strong&gt;: &lt;code&gt;@notionhq/client&lt;/code&gt; — 10 MCP-compatible tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transport&lt;/strong&gt;: Server-Sent Events for real-time streaming&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The 10 Notion MCP Tools
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NOTION_TOOLS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;search_notion&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;// Full-text search across workspace&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create_notion_page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// Create pages with rich markdown → block conversion&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;get_page_content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;// Read any page's full content&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;update_notion_page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// Append structured content to existing pages&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create_project_database&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Task DB: Status, Priority, Due Date, Assignee, Tags&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;query_database&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// Retrieve records with optional filters&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;get_workspace_overview&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Scan recent pages and databases&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add_database_item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;// Insert rows with proper property types&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create_goals_tracker&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// OKR DB: Objective/KR, Progress %, Owner, Quarter&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create_content_calendar&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Editorial DB: Channel, Type, Status, Publish Date&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tools are defined in OpenAI-compatible format (which Groq uses), so each tool looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;create_notion_page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Create a new page in Notion with rich content...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Title of the new page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Page content in markdown format...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Emoji icon for the page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nx"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Multi-Turn Streaming Loop
&lt;/h3&gt;

&lt;p&gt;This is the core of the whole thing. The AI doesn't just make one tool call — it chains as many as needed, reasoning about results before deciding what to do next:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;groq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Groq&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GROQ_API_KEY&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Keep looping until the model stops using tools&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;streamResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;groq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&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="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;llama-3.3-70b-versatile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NOTION_TOOLS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;conversationHistory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Accumulate streamed tool call fragments&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolCallsMap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;streamResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Stream text chunks to the frontend in real-time&lt;/span&gt;
      &lt;span class="nf"&gt;sendSSE&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&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="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Accumulate streamed JSON fragments per tool call index&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;toolCallsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="nx"&gt;toolCallsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;toolCallsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;toolCallsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;toolCallsMap&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arguments&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="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolCalls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toolCallsMap&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toolCalls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// No more tool calls — done&lt;/span&gt;

  &lt;span class="c1"&gt;// Notify frontend each tool is starting&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;toolCalls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;sendSSE&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool_start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arguments&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="c1"&gt;// Add assistant message with tool_calls to history&lt;/span&gt;
  &lt;span class="nx"&gt;conversationHistory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assistant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toolCalls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;function&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arguments&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="c1"&gt;// Execute each tool against the Notion API&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;toolCalls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;executeTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nf"&gt;sendSSE&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool_result&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Feed result back as a tool message for the next reasoning step&lt;/span&gt;
    &lt;span class="nx"&gt;conversationHistory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tool&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;tool_call_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key insight: the AI sees the &lt;em&gt;result&lt;/em&gt; of each Notion operation before deciding what to do next. It's not blindly firing off a pre-planned list — it's actually reading what it created and adapting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Markdown → Notion Blocks
&lt;/h3&gt;

&lt;p&gt;One of the trickier engineering challenges: Notion's API doesn't accept markdown. Every page has to be structured as typed block objects. I wrote a full converter that handles 8 block types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;markdownToBlocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;markdown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;NotionBlock&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;# &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;heading1Block&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;## &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;heading2Block&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;### &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;heading3Block&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;- &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;bulletBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt; /&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;numberedBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="sr"&gt; /&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;quoteBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;---&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;dividerBlock&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;             &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;paragraphBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;return&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Headings, bullets, numbered lists, quotes, dividers, paragraphs — all properly typed and sent to Notion's API.&lt;/p&gt;

&lt;h3&gt;
  
  
  OKR Database Schema
&lt;/h3&gt;

&lt;p&gt;When you say "set up my Q2 OKRs", Apex builds a database with exactly the right schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;okrSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&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="na"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Objective&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Key Result&lt;/span&gt;&lt;span class="dl"&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="na"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not Started&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;On Track&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;At Risk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Behind&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Complete&lt;/span&gt;&lt;span class="dl"&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="na"&gt;Progress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;percent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;Owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;rich_text&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Due Date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;date&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="na"&gt;Quarter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;period&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="na"&gt;Notes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;rich_text&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not a generic template. A purpose-built structure that matches how real OKR systems work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Features That Make the UX Sing
&lt;/h2&gt;

&lt;p&gt;Beyond the core AI functionality, I obsessed over the interface:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;⌘K Command Palette&lt;/strong&gt; — Hit Cmd+K to open a searchable command palette. Switch modes, fire quick actions, export your conversation, clear the session — all without touching the mouse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Slash Commands&lt;/strong&gt; — Type &lt;code&gt;/project&lt;/code&gt;, &lt;code&gt;/goals&lt;/code&gt;, &lt;code&gt;/meeting&lt;/code&gt; directly in the chat input to instantly switch modes. Feels like a native app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Voice Input&lt;/strong&gt; — Click the mic button and just talk. Web Speech API converts your speech to text in real time, with animated pulse rings showing it's listening. Perfect for actual brain dumps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smart Follow-Up Suggestions&lt;/strong&gt; — After every AI response, three contextual next-step prompts appear. Click any to instantly continue. It's like the AI is guiding you toward the next useful thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session Stats Bar&lt;/strong&gt; — A live counter in the top bar shows pages created, databases built, and total Notion operations performed this session. It's a small thing but makes the productivity feel visceral.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Floating Success Toasts&lt;/strong&gt; — Every time a Notion page or database is created, a beautiful animated toast slides up: &lt;em&gt;"Page created: Q2 OKR Tracker — saved to Notion"&lt;/em&gt;. Instant feedback, no hunting through your workspace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Export Conversation&lt;/strong&gt; — Download your entire session as a formatted markdown file. Great for sharing what you built.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workspace Dashboard&lt;/strong&gt; — A separate &lt;code&gt;/dashboard&lt;/code&gt; route showing live workspace stats, recent pages and databases, a full capability showcase, and a visual "How Apex Works" flow diagram.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Demo: OKR Mode in Action
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What I typed:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Set up Q2 OKRs — grow MRR by 40%, improve activation rate to 60%, ship mobile v1, and reduce churn below 3%"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;What Apex did (30 seconds):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Scanned workspace for existing goal-related pages&lt;/li&gt;
&lt;li&gt;Created a &lt;code&gt;🎯 Goals Hub&lt;/code&gt; page with vision statement and OKR methodology explained&lt;/li&gt;
&lt;li&gt;Built the &lt;code&gt;Q2 OKR Tracker&lt;/code&gt; database with 8 properly typed fields&lt;/li&gt;
&lt;li&gt;Added each of the 4 objectives as database records (Type: Objective)&lt;/li&gt;
&lt;li&gt;Added 3 key results per objective (Type: Key Result, with measurable targets)&lt;/li&gt;
&lt;li&gt;Created a &lt;code&gt;📋 Weekly Check-in Template&lt;/code&gt; page — duplicate this every Monday&lt;/li&gt;
&lt;li&gt;Created a &lt;code&gt;🏆 Wins &amp;amp; Learnings Log&lt;/code&gt; for retrospectives&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What I had to do:&lt;/strong&gt; Type one sentence.&lt;/p&gt;

&lt;p&gt;That's the whole thing.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scheduled Reports&lt;/strong&gt; — Auto-run weekly review every Monday morning via cron&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notion Webhooks&lt;/strong&gt; — React to workspace changes in real time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-workspace&lt;/strong&gt; — Switch between different Notion accounts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Template Library&lt;/strong&gt; — Pre-built prompts for 20+ common use cases&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Setup in 3 Minutes
&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/Aryakoste/apex-notion
&lt;span class="nb"&gt;cd &lt;/span&gt;apex-notion-ai
npm &lt;span class="nb"&gt;install
cp&lt;/span&gt; .env.local.example .env.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit &lt;code&gt;.env.local&lt;/code&gt;:&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="nv"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gsk_...
&lt;span class="nv"&gt;NOTION_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret_...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;span class="c"&gt;# Open http://localhost:3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Getting your Groq API key (free):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://console.groq.com" rel="noopener noreferrer"&gt;console.groq.com&lt;/a&gt; → sign up (no credit card)&lt;/li&gt;
&lt;li&gt;API Keys → Create API Key → copy it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Getting your Notion API key:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://notion.so/my-integrations" rel="noopener noreferrer"&gt;notion.so/my-integrations&lt;/a&gt; → New integration → copy the secret&lt;/li&gt;
&lt;li&gt;On each Notion page: &lt;code&gt;...&lt;/code&gt; menu → &lt;strong&gt;Add connections&lt;/strong&gt; → select your integration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. Everything else is handled by Apex.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters Beyond the Demo
&lt;/h2&gt;

&lt;p&gt;The reason I'm excited about this isn't the cool UI or the streaming animations — it's what it represents for how we use tools.&lt;/p&gt;

&lt;p&gt;Notion has always required you to be the architect. You had to know what a good project page looks like. You had to remember to run your weekly review. You had to structure your OKRs correctly.&lt;/p&gt;

&lt;p&gt;With MCP, the AI can be the architect. You just have to know &lt;em&gt;what you want&lt;/em&gt;. The gap between intention and implementation collapses from hours to seconds.&lt;/p&gt;

&lt;p&gt;I think this is the future of productivity software. Not AI that suggests. AI that &lt;em&gt;does&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub
&lt;/h2&gt;

&lt;p&gt;Full source code: &lt;strong&gt;[&lt;a href="https://github.com/Aryakoste/apex-notion" rel="noopener noreferrer"&gt;https://github.com/Aryakoste/apex-notion&lt;/a&gt;]&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;code&gt;#notionmcp&lt;/code&gt; &lt;code&gt;#ai&lt;/code&gt; &lt;code&gt;#nextjs&lt;/code&gt; &lt;code&gt;#typescript&lt;/code&gt; &lt;code&gt;#groq&lt;/code&gt; &lt;code&gt;#llama&lt;/code&gt; &lt;code&gt;#productivity&lt;/code&gt; &lt;code&gt;#buildinpublic&lt;/code&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>SkillSwap Local: Trading Plumbing Skills for React Lessons with Neighbors</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Sun, 01 Mar 2026 22:15:27 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/skillswap-local-building-a-hyperlocal-web-of-shared-knowledge-56mk</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/skillswap-local-building-a-hyperlocal-web-of-shared-knowledge-56mk</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.clauneck.workers.dev/challenges/weekend-2026-02-28"&gt;DEV Weekend Challenge: Community&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Have you ever stared at a leaky faucet, wrench in hand, wishing you knew someone—anyone—who could just show you what to do? Or perhaps you're a seasoned baker whose sourdough starter is practically a family heirloom, and you'd love to teach a neighbor the art of the perfect crust in exchange for some tech-support for your laptop?&lt;/p&gt;

&lt;p&gt;That's the core of my submission for the &lt;strong&gt;Build for Your Community&lt;/strong&gt; challenge: &lt;strong&gt;SkillSwap Local&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;It’s completely localized, meaning you aren't shouting into the digital void. You are talking to people blocks away from you. It’s a platform designed specifically to turn strangers in your immediate vicinity into collaborators, teachers, and friends.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤝 The Community &amp;amp; The Problem
&lt;/h2&gt;

&lt;p&gt;I live in a bustling neighborhood where people are incredibly busy. Despite living shoulder-to-shoulder, the modern paradox is that we barely know each other. We hire expensive contractors for minor fixes, struggle alone with new software, or let our own unique talents gather dust. &lt;/p&gt;

&lt;p&gt;The community I wanted to serve was my own neighborhood—and by extension, &lt;em&gt;any&lt;/em&gt; local neighborhood. The problem isn't a lack of willingness to help; it's a lack of a structured, safe, and engaging way to connect &lt;em&gt;needs&lt;/em&gt; with &lt;em&gt;skills&lt;/em&gt; locally. &lt;/p&gt;

&lt;p&gt;Why pay a premium for a service when the person three houses down loves doing it and just needs help learning React in return?&lt;/p&gt;

&lt;h2&gt;
  
  
  ✨ The Solution: SkillSwap Local
&lt;/h2&gt;

&lt;p&gt;SkillSwap Local bridges the gap between digital convenience and physical proximity. It’s an interactive, visually stunning platform built on the premise of the barter system, elevated for the modern localized web.&lt;/p&gt;

&lt;p&gt;It is a hyperlocal barter platform where neighbors exchange skills instead of cash—plumbing for React mentoring, guitar lessons for UX reviews—discoverable through a live neighborhood map and backed by real‑time chat.&lt;/p&gt;

&lt;h3&gt;
  
  
  🌟 Key Features &amp;amp; Value Proposition
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Smart Matching System:&lt;/strong&gt;&lt;br&gt;
Forget endless scrolling. SkillSwap uses a "Smart Match" algorithm that pairs people whose "offered skills" directly match another person's "needed skills"—creating instant, mutually beneficial relationships.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Interactive Neighborhood Radar (Map View):&lt;/strong&gt;&lt;br&gt;
I didn't just want a list of users. I wanted users to &lt;em&gt;see&lt;/em&gt; their community. Using Leaflet, the interactive Map View drops pins of nearby skill-sharers and open requests, turning your neighborhood into a map of opportunities. It defaults to your local area, creating an immediate sense of geographic belonging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Real-Time Chat &amp;amp; Collaboration:&lt;/strong&gt;&lt;br&gt;
When a match is made, communication needs to be seamless. Built with robust Socket.io integration, the app features instant real-time messaging, allowing groups and individuals to coordinate meetups, share files, and barter without leaving the platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The Requests Board &amp;amp; Social Feed:&lt;/strong&gt;&lt;br&gt;
Need something specific right now? Post it to the Requests Board. Neighbors can accept quests—like "need help assembling an IKEA desk"—fostering a gamified sense of helpfulness. The social feed allows users to post updates, share community news, and celebrate successful swaps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Community Leaderboard:&lt;/strong&gt;&lt;br&gt;
A subtle layer of gamification! The leaderboard highlights the most helpful community members. Earning points by teaching, helping, and successfully completing requests adds a layer of fun and accountability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Polished, Premium UI:&lt;/strong&gt;&lt;br&gt;
I specifically aimed for a high-end, glassmorphism-inspired dark theme. Why? Because community apps often look like bulletin boards from 1999. I wanted this to feel modern, engaging, and worthy of its users' time. The UI is rich with subtle micro-animations that make exploring your neighborhood feel alive.&lt;/p&gt;
&lt;h2&gt;
  
  
  🛠️ Technical Execution
&lt;/h2&gt;

&lt;p&gt;I wanted the architecture to be as robust as the community it aims to build.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; Built with React (Vite/CRA), leveraging dynamic routing and Context API for state management. The UI strictly adheres to modern web design principles—utilizing custom CSS (no generic templates here) to achieve a deeply tailored glassmorphic dark mode, smooth transitions, and a premium feel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend:&lt;/strong&gt; A scalable Node.js/Express architecture backed by Sequelize (SQLite for ease of local deployment, easily interchangeable).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time:&lt;/strong&gt; Socket.io powers the chat experience, handling private messaging and group channels with low latency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Geospatial:&lt;/strong&gt; &lt;code&gt;react-leaflet&lt;/code&gt; integrates map views directly into the dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment &amp;amp; Config:&lt;/strong&gt; Everything is easily configurable via &lt;code&gt;.env&lt;/code&gt; files. The API URLs are perfectly isolated so that deployment from a local dev server to a cloud provider is as simple as flipping an environment switch.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🎨 Creativity &amp;amp; The "Spark a Smile" Factor
&lt;/h2&gt;

&lt;p&gt;The most creative aspect of SkillSwap Local isn't just the code—it's the &lt;em&gt;interactions&lt;/em&gt; it encourages. The "Radar" view feels a bit like a video game mini-map, turning the mundane task of finding a plumber into a localized quest. The gamified leaderboards add a lighthearted, slightly competitive (but overwhelmingly positive) flair to being a "good neighbor." &lt;/p&gt;

&lt;p&gt;It genuinely sparks a smile when you realize the person who can finally fix your bicycle gears is the same person you wave to every morning at the coffee shop.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/ibtY9_Y6fEM"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

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

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Aryakoste" rel="noopener noreferrer"&gt;
        Aryakoste
      &lt;/a&gt; / &lt;a href="https://github.com/Aryakoste/skillSwap" rel="noopener noreferrer"&gt;
        skillSwap
      &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;SkillSwap Local&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;SkillSwap Local is a hyperlocal skill exchange platform where users can offer their skills and learn from others in their community. Connect with nearby users, chat in real-time, view users on an interactive map, and share posts!&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;✨ Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Smart Matching &amp;amp; Radar&lt;/strong&gt;: Find nearby users offering skills you want and wanting skills you offer. View their location on an interactive map (Leaflet).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Chat&lt;/strong&gt;: Seamless communication with matches using Socket.io.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community Wall&lt;/strong&gt;: Share posts, requests, and tips with the community.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich User Profiles&lt;/strong&gt;: Display skills offered and wanted in a categorized, polished UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Premium UI&lt;/strong&gt;: Modern dark theme with glassmorphism and smooth animations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database&lt;/strong&gt;: Uses SQLite for local development and easily switchable to MySQL for production.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🛠️ Tech Stack&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Node.js, Express.js, Sequelize (SQLite/MySQL), Socket.io, JWT Authentication, Multer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: React, React Router, React Leaflet, Lucide React, Socket.io-client&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Getting&lt;/h2&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/Aryakoste/skillSwap" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;h2&gt;
  
  
  🛠️ Live Deployment
&lt;/h2&gt;

&lt;p&gt;Deployed on Google Cloud Run with Docker containers. Working demo: &lt;a href="https://skillswap-frontend-818474269873.us-central1.run.app/login" rel="noopener noreferrer"&gt;skillswap-frontend-818474269873.us-central1.run.app/login&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;SkillSwap Local isn't just an app; it's a digital catalyst for real-world interactions. In a time when we've never been more connected globally, we've never been more disconnected locally. This project was my attempt to use modern web technologies—real-time sockets, geolocation, and algorithmic matching—to solve a very old, very human problem: getting to know our neighbors.&lt;/p&gt;

&lt;p&gt;Thank you to the community for this challenge, and I hope SkillSwap Local inspires you to knock on a door, share a skill, and build your own local fabric!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you'd like to check out the repo or contribute to bringing SkillSwap to your own neighborhood, let me know in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>DepDoctor: Stop Getting Hacked by Outdated Dependencies (Dependency Hell)</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Sun, 15 Feb 2026 20:15:57 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/depdoctor-stop-getting-hacked-by-outdated-dependencies-dependency-hell-3gcb</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/depdoctor-stop-getting-hacked-by-outdated-dependencies-dependency-hell-3gcb</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.clauneck.workers.dev/challenges/github-2026-01-21"&gt;GitHub Copilot CLI Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The "Dependency Hell" Nightmare 😱
&lt;/h1&gt;

&lt;p&gt;It's 4:55 PM on a Friday. You're about to deploy.&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="nv"&gt;$ &lt;/span&gt;npm audit
found 12 vulnerabilities &lt;span class="o"&gt;(&lt;/span&gt;2 critical, 5 high&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Panic sets in.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You check the report. The critical vulnerability isn't even in &lt;em&gt;your&lt;/em&gt; code. It's in &lt;code&gt;left-pad-v2&lt;/code&gt;, which is a dependency of &lt;code&gt;react-awesome-button&lt;/code&gt;, which is a dependency of your UI library...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You are now in Dependency Hell.&lt;/strong&gt; 🔥&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ You can't just &lt;code&gt;npm update&lt;/code&gt; (it breaks the UI).&lt;/li&gt;
&lt;li&gt;❌ You can't remove the package (you need the button).&lt;/li&gt;
&lt;li&gt;❌ You spend hours reading GitHub issues from 2019.&lt;/li&gt;
&lt;li&gt;❌ You try &lt;code&gt;npm dedupe&lt;/code&gt;, &lt;code&gt;npm audit fix --force&lt;/code&gt;... and now your app won't build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sound familiar?&lt;/p&gt;




&lt;h2&gt;
  
  
  The "Aha!" Moment
&lt;/h2&gt;

&lt;p&gt;What if &lt;strong&gt;AI could explain&lt;/strong&gt; vulnerabilities in plain English?&lt;/p&gt;

&lt;p&gt;What if it could tell me the &lt;strong&gt;business impact&lt;/strong&gt; ($$$)?&lt;/p&gt;

&lt;p&gt;What if it could &lt;strong&gt;auto-fix&lt;/strong&gt; everything in 30 seconds?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enter DepDoctor&lt;/strong&gt; 🩺&lt;/p&gt;




&lt;h2&gt;
  
  
  🩺 What is DepDoctor?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;DepDoctor&lt;/strong&gt; is an AI-powered CLI tool that doesn't just &lt;em&gt;find&lt;/em&gt; problems—it &lt;strong&gt;fixes&lt;/strong&gt; them.&lt;/p&gt;

&lt;p&gt;It combines &lt;strong&gt;GitHub Copilot's&lt;/strong&gt; reasoning engine with a smart &lt;strong&gt;Tree Repair System&lt;/strong&gt; to surgically remove vulnerabilities from your &lt;code&gt;node_modules&lt;/code&gt; without breaking your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Killer Feature": Smart Tree Repair 🌳
&lt;/h3&gt;

&lt;p&gt;Most tools stop at "You have a problem." DepDoctor says, &lt;strong&gt;"I fixed it."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Smart Tree Repair&lt;/strong&gt; uses a multi-stage process to resolve "Dependency Hell":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Deep Scan&lt;/strong&gt;: Finds vulnerabilities nested 10 layers deep.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Safe Version Resolution&lt;/strong&gt;: Finds the &lt;em&gt;exact&lt;/em&gt; version of the sub-dependency that fixes the CVE.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Surgical Override&lt;/strong&gt;: Automatically modifies your &lt;code&gt;package.json&lt;/code&gt; with an &lt;code&gt;overrides&lt;/code&gt; (or &lt;code&gt;resolutions&lt;/code&gt;) field to force &lt;em&gt;only&lt;/em&gt; the vulnerable package to update, keeping the rest of the chain intact.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Auto-Dedupe&lt;/strong&gt;: Flattens your tree to remove duplicate vulnerable copies.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Result?&lt;/strong&gt;&lt;br&gt;
You type &lt;code&gt;depdoctor --fix-all&lt;/code&gt;, and that unfixable nested vulnerability vanishes. ✨&lt;/p&gt;


&lt;h2&gt;
  
  
  🤖 Copilot: Your Security Analyst
&lt;/h2&gt;

&lt;p&gt;DepDoctor uses &lt;strong&gt;GitHub Copilot CLI&lt;/strong&gt; to translate "Security Speak" into "Business Speak".&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;CVE-2024-1234: Prototype pollution in object serialization...&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;DepDoctor shows:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🤖 Copilot Analysis:&lt;/strong&gt;&lt;br&gt;
"Attackers can crash your server by sending malformed JSON.&lt;br&gt;
&lt;strong&gt;Business Impact:&lt;/strong&gt; High risk of DoS attack during peak traffic (est. loss $10k/hour)."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It prioritizes fixes based on &lt;strong&gt;actual risk&lt;/strong&gt;, not just scary red text.&lt;/p&gt;


&lt;h3&gt;
  
  
  The Demo That Made My Team Go "😮"
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;depdoctor

🩺 DepDoctor - Analyzing dependencies...

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 DEPENDENCY HEALTH REPORT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Overall Score: 68/100 🟡 &lt;span class="o"&gt;(&lt;/span&gt;Needs Attention&lt;span class="o"&gt;)&lt;/span&gt;

🔴 CRITICAL &lt;span class="o"&gt;(&lt;/span&gt;2 vulnerabilities&lt;span class="o"&gt;)&lt;/span&gt;
┌─────────────────────────────────────────┐
│ lodash@4.17.21                          │
│ CVE-2021-23337 - Prototype Pollution    │
│                                         │
│ 🤖 Copilot Explains:                   │
│ &lt;span class="s2"&gt;"Attacker can modify object properties, │
│  leading to Remote Code Execution"&lt;/span&gt;      │
│                                         │
│ 💰 Business Impact: &lt;span class="nv"&gt;$50&lt;/span&gt;,000+ breach    │
│                                         │
│ ✅ Fix: npm &lt;span class="nb"&gt;install &lt;/span&gt;lodash@latest      │
└─────────────────────────────────────────┘

Apply fixes? &lt;span class="o"&gt;[&lt;/span&gt;y/N]: y

✅ Fixed 2 critical vulnerabilities &lt;span class="k"&gt;in &lt;/span&gt;30 seconds!
New Score: 92/100 🟢
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;No more Googling CVE numbers at midnight!&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  🚀 See It In Action
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. The Audit
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;depdoctor

🩺 DepDoctor - Analyzing dependencies...

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 DEPENDENCY HEALTH REPORT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

🔴 CRITICAL: deep-merge-util
   In: ui-lib &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; button &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; utils &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; deep-merge-util

   🤖 Copilot says: &lt;span class="s2"&gt;"Allows Remote Code Execution (RCE)."&lt;/span&gt;
   💰 Risk: Critical Data Breach

Dependencies stuck &lt;span class="k"&gt;in &lt;/span&gt;Hell? 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2. The Cure
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;depdoctor &lt;span class="nt"&gt;--fix-all&lt;/span&gt;

🌳 Activating Smart Tree Repair...
   • Running npm dedupe... Done.
   • Isolating nested vulnerability: deep-merge-util
   • Calculating safe override version... found v2.1.0
   • Applying surgical override to package.json...
   • Re-installing dependencies...

✅ DEPENDENCY HELL RESOLVED.
   2 Nested Vulnerabilities Fixed.
   0 Breaking Changes Detected.

Get back to your weekend! 🍻
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Exists
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;Developers waste &lt;strong&gt;15-20 hours/week&lt;/strong&gt; on dependency hell:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ npm audit shows 47 vulnerabilities... &lt;strong&gt;which ones matter?&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;❌ Outdated packages... &lt;strong&gt;which will break my app?&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;❌ Unused deps... &lt;strong&gt;how much am I wasting?&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;❌ Hours spent &lt;strong&gt;Googling CVEs&lt;/strong&gt; and reading changelogs&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🛠️ How It Works (Under the Hood)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────┐
│ Your Project│
└──────┬──────┘
       │
       ▼
┌─────────────────┐
│ npm audit       │  ← Scan vulnerabilities
│ npm outdated    │  ← Find outdated packages
│ Code Scanner    │  ← Detect unused deps
└──────┬──────────┘
       │
       ▼
┌─────────────────────────┐
│ GitHub Copilot CLI      │
│ • Explain vulnerabilities│  ← AI magic here! 🤖
│ • Assess business impact │
│ • Generate fixes         │
│ • Create migration guides│
└──────┬──────────────────┘
       │
       ▼
┌─────────────────┐
│ Beautiful Report│  ← You see this! 🎨
│ + Auto-fix      │
└─────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For the nerds like me, here's how the &lt;strong&gt;Tree Fixer&lt;/strong&gt; works (&lt;code&gt;src/fixers/tree-fixer.ts&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Identify nested vulnerabilities&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nestedVulns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vulnerabilities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isDirect&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Copilot determines the safe patch version&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;overrides&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;vuln&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;nestedVulns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;safeVer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;copilot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findSafeVersion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;vuln&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;overrides&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;vuln&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;safeVer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Apply 'overrides' to package.json (works for npm 8+)&lt;/span&gt;
&lt;span class="nx"&gt;packageJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overrides&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;packageJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;overrides&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;overrides&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;package.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;packageJson&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It leverages the native &lt;code&gt;overrides&lt;/code&gt; feature of npm (and &lt;code&gt;resolutions&lt;/code&gt; for yarn) but automates the &lt;strong&gt;tedious, error-prone part&lt;/strong&gt;: figuring out &lt;em&gt;what&lt;/em&gt; to override and &lt;em&gt;to what version&lt;/em&gt; to avoid breaking changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Impact: Before vs After
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Before DepDoctor:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Friday 11 PM: npm audit shows 12 vulnerabilities
Friday 11:05 PM: Google "CVE-2021-23337"
Friday 11:30 PM: Still reading security advisories
Saturday 2 AM: Finally fix 2 critical issues
Monday: Boss asks "why was the site down?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  After DepDoctor:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Friday 11 PM: depdoctor
Friday 11:01 PM: See AI explanations
Friday 11:01 PM: Press 'y' to auto-fix
Friday 11:02 PM: Done. Score: 92/100 🟢
Friday 11:03 PM: Sleep like a baby 😴
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Time saved: 3 hours → 2 minutes&lt;/strong&gt; ⏰&lt;/p&gt;




&lt;h2&gt;
  
  
  Screenshots
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fpbgxahltvkumitnh7s6q.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.amazonaws.com%2Fuploads%2Farticles%2Fpbgxahltvkumitnh7s6q.png" alt=" " width="800" height="695"&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2Fiiribeax3qb6iqul5q6t.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.amazonaws.com%2Fuploads%2Farticles%2Fiiribeax3qb6iqul5q6t.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;From source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Aryakoste/depDoctor
&lt;span class="nb"&gt;cd &lt;/span&gt;depDoctor
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run build
npm &lt;span class="nb"&gt;link
&lt;/span&gt;depdoctor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Cool Features You Might Miss
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Health History Tracking&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;depdoctor &lt;span class="nb"&gt;history&lt;/span&gt;

┌─────────────────────┬─────────┬──────────┬──────┐
│ Date                │ Score   │ Critical │ High │
├─────────────────────┼─────────┼──────────┼──────┤
│ 2/15/2026, 1:00 PM  │ 92/100🟢│ 0        │ 1    │
│ 2/14/2026, 11:00 PM │ 68/100🟡│ 2        │ 5    │
└─────────────────────┴─────────┴──────────┴──────┘

📈 Score improved by 24 points!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;CI/CD Integration&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/security.yml&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;Check Dependencies&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;npm install -g depdoctor&lt;/span&gt;
    &lt;span class="s"&gt;depdoctor --ci --threshold critical&lt;/span&gt;
  &lt;span class="c1"&gt;# Fails build if critical vulns found&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;strong&gt;Migration Guides for Updates&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;🟡 react: 17.0.2 → 18.3.1

🤖 Copilot Migration:
1. Update package.json
2. Replace ReactDOM.render&lt;span class="o"&gt;()&lt;/span&gt; → createRoot&lt;span class="o"&gt;()&lt;/span&gt;
3. Remove deprecated lifecycle methods

⏰ Est. &lt;span class="nb"&gt;time&lt;/span&gt;: 2 hours
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;What dependency horror stories do you have? Share in the comments!&lt;/strong&gt; 💬&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Made with ❤️ and GitHub Copilot CLI&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/Aryakoste/depDoctor" rel="noopener noreferrer"&gt;⭐ Star on GitHub&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>Every Developer’s Worst Command — Now With an Undo Button</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Sun, 15 Feb 2026 16:19:26 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/every-developers-worst-command-now-with-an-undo-button-10m8</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/every-developers-worst-command-now-with-an-undo-button-10m8</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.clauneck.workers.dev/challenges/github-2026-01-21"&gt;GitHub Copilot CLI Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  😱 The "Oh No" Moment
&lt;/h2&gt;

&lt;p&gt;You’re in the zone, hacking away at 2 AM.&lt;br&gt;&lt;br&gt;
You copy a command from Stack Overflow, paste it, hit Enter...  &lt;/p&gt;

&lt;p&gt;And then that deep, primal dread hits you.  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Wait. Did I just nuke my entire project?”&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;“Was that script from 2012 even safe?”&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;“Why is my fan spinning up like a jet engine?”&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;We’ve all been there.&lt;br&gt;&lt;br&gt;
In the AI era, we’re copying faster than we’re thinking — and sometimes, that’s a recipe for digital disaster.&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;🛡️ CommandGuard — your terminal’s guardian angel.&lt;/strong&gt;&lt;/p&gt;


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

&lt;p&gt;&lt;strong&gt;CommandGuard&lt;/strong&gt; is the ultimate terminal safety net.&lt;br&gt;&lt;br&gt;
It’s the &lt;em&gt;“Are you sure about that?”&lt;/em&gt; voice you wish you had &lt;em&gt;before&lt;/em&gt; catastrophic commands strike.  &lt;/p&gt;

&lt;p&gt;Instead of just blocking &lt;code&gt;rm -rf /&lt;/code&gt; using regex, CommandGuard uses &lt;strong&gt;GitHub Copilot CLI&lt;/strong&gt; to actually &lt;strong&gt;understand&lt;/strong&gt; the intent behind your commands.  &lt;/p&gt;

&lt;p&gt;It:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Analyzes&lt;/strong&gt; the command’s purpose.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explains&lt;/strong&gt; what it &lt;em&gt;really&lt;/em&gt; does — in plain English.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Suggests&lt;/strong&gt; safer alternatives.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It’s like having that one senior DevOps engineer who calmly saves you from yourself.&lt;/p&gt;



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

&lt;ol&gt;
&lt;li&gt; User types: &lt;code&gt;curl http://sketchy-site.com/run.sh | bash&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;CommandGuard Intercepts!&lt;/strong&gt; 🛑&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Copilot Analysis:&lt;/strong&gt; "This command downloads and executes a remote script immediately. This is high risk."&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Suggestion:&lt;/strong&gt; "Download the script first, inspect it, then run it."&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  📸 Screenshots
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fqvlv75km0uctq3ysnsi0.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.amazonaws.com%2Fuploads%2Farticles%2Fqvlv75km0uctq3ysnsi0.png" alt=" " width="800" height="404"&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2Fe9gy9a6webvdsdbj1fun.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.amazonaws.com%2Fuploads%2Farticles%2Fe9gy9a6webvdsdbj1fun.png" alt=" " width="800" height="144"&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2F6bmvcitujn7nx7ijunuw.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.amazonaws.com%2Fuploads%2Farticles%2F6bmvcitujn7nx7ijunuw.png" alt=" " width="800" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have also included powershell and terminal hooks to intercept commands in real time but if you are worried. I would just recommend just use the commandguard cli interface.&lt;/p&gt;


&lt;h2&gt;
  
  
  🛠️ How It Works (The "Wacky" Part)
&lt;/h2&gt;

&lt;p&gt;This isn't just a bash alias. It's a full-blown interception system.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Node.js + TypeScript&lt;/strong&gt;: The brain.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Commander.js&lt;/strong&gt;: The CLI framework.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;GitHub Copilot CLI&lt;/strong&gt;: The intelligence.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;SQLite&lt;/strong&gt;: The memory (keeps track of your accidental near-misses).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Chalk + Boxen&lt;/strong&gt;: The style.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  The Architecture
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph TD
    A[User types command] --&amp;gt;|Intercept| B(Shell Hook)
    B --&amp;gt; C{Is it dangerous?}
    C -- No --&amp;gt; D[Execute Command]
    C -- Yes --&amp;gt; E[Call GitHub Copilot]
    E --&amp;gt; F[Analyze Risk &amp;amp; Generate Explanation]
    F --&amp;gt; G[Display Warning UI]
    G --&amp;gt; H{User Action}
    H -- Abort --&amp;gt; I[Safe!]
    H -- Proceed --&amp;gt; D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Intercept&lt;/strong&gt;: You type a command. CommandGuard hooks into your shell (Bash, Zsh, PowerShell).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analyze&lt;/strong&gt;: It sends the command to GitHub Copilot's CLI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assess&lt;/strong&gt;: The AI evaluates the risk. Is this command destructive? Is it common?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explain&lt;/strong&gt;: It breaks down &lt;em&gt;exactly&lt;/em&gt; what the command will do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decide&lt;/strong&gt;: You get a clear, interactive prompt.

&lt;ul&gt;
&lt;li&gt;  🚫 &lt;strong&gt;Abort&lt;/strong&gt;: Stop it in its tracks.&lt;/li&gt;
&lt;li&gt;  ✅ &lt;strong&gt;Proceed&lt;/strong&gt;: Run it (if you're sure).&lt;/li&gt;
&lt;li&gt;  💡 &lt;strong&gt;Alternative&lt;/strong&gt;: Run a safer version suggested by the AI.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Or if you are worried about typing any command just ask away and it will suggest you the command.&lt;/p&gt;


&lt;h2&gt;
  
  
  🏆 Category Submission: &lt;strong&gt;Wacky Wildcards&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Why wacky? because I'm basically asking an AI to police my shell. It's an AI judging another AI's output (if you got the command from ChatGPT). It's &lt;strong&gt;AI-ception&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  🚀 Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Real-time Interception&lt;/strong&gt;: Hooks directly into &lt;code&gt;bash&lt;/code&gt; and &lt;code&gt;zsh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;AI-Powered Context&lt;/strong&gt;: Understands &lt;em&gt;why&lt;/em&gt; a command is dangerous, not just &lt;em&gt;that&lt;/em&gt; it's dangerous.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Disaster Counter&lt;/strong&gt;: A dashboard showing how many times you almost destroyed your PC.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Educational&lt;/strong&gt;: Teaches you &lt;em&gt;why&lt;/em&gt; &lt;code&gt;chmod 777&lt;/code&gt; is bad, better than any tutorial.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Suggestions&lt;/strong&gt;: You can also write which command you want and it will suggest you right away.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🏃‍♂️ Try It Out
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="c"&gt;# Install directly from GitHub&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; github:Aryakoste/commandguard

&lt;span class="c"&gt;# Setup the hooks&lt;/span&gt;
commandguard setup

&lt;span class="c"&gt;# Restart your terminal&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's it. Your terminal is now guarded.&lt;/p&gt;

&lt;p&gt;Now you can also use its cli use.&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;# Analyze the command&lt;/span&gt;
commandguard analyze &lt;span class="s2"&gt;"rm -rf"&lt;/span&gt;

&lt;span class="c"&gt;# Intercept the command&lt;/span&gt;
commandguard intercept &lt;span class="s2"&gt;"del /s /q"&lt;/span&gt;

&lt;span class="c"&gt;# Suggest an command&lt;/span&gt;
commandguard suggest &lt;span class="s2"&gt;"push all my files in github repository"&lt;/span&gt;

&lt;span class="c"&gt;# See the dashboard&lt;/span&gt;
commandguard dashboard

&lt;span class="c"&gt;# See all the commands&lt;/span&gt;
commandguard &lt;span class="nb"&gt;help&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚙️ Configuration
&lt;/h2&gt;

&lt;p&gt;Want to tweak how CommandGuard behaves? You can configure it to your liking.&lt;/p&gt;

&lt;p&gt;For example, to enable the AI-only mode (which skips local checks and goes straight to Copilot for everything), run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;commandguard config &lt;span class="nb"&gt;set &lt;/span&gt;ai-mode &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔮 Future Plans
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Team Policies&lt;/strong&gt;: Share blocked command lists with your team.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;VS Code Extension&lt;/strong&gt;: visual warnings in the integrated terminal.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/Aryakoste/commandguard" rel="noopener noreferrer"&gt;https://github.com/Aryakoste/commandguard&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Made with ❤️, ☕, and a healthy fear of &lt;code&gt;sudo&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>⚡ Back to the Roots: A Retro Terminal Portfolio That Takes You to 1995 🖥️</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Sun, 01 Feb 2026 17:45:36 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/back-to-the-roots-a-retro-terminal-portfolio-that-takes-you-to-1995-2ehb</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/back-to-the-roots-a-retro-terminal-portfolio-that-takes-you-to-1995-2ehb</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.clauneck.workers.dev/challenges/new-year-new-you-google-ai-2025-12-31"&gt;New Year, New You Portfolio Challenge Presented by Google AI&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🖥️ System.Init() &amp;gt; About Me
&lt;/h2&gt;

&lt;p&gt;Hello, World! I'm &lt;strong&gt;Arya Khochare&lt;/strong&gt;, a developer who believes that sometimes, to move forward, you have to look back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remember the early 2000s?&lt;/strong&gt; When portfolios were viewed in terminal windows, when green phosphor monitors were cutting-edge, and when hackers typed &lt;code&gt;cat portfolio.txt&lt;/code&gt; to see your resume? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yeah, those were the days.&lt;/strong&gt; 🕹️&lt;/p&gt;

&lt;p&gt;🎯 What I Wanted to Express:&lt;/p&gt;

&lt;p&gt;Technical Roots: A tribute to the command-line interfaces that shaped modern development&lt;br&gt;
Personality Through Code: Not just another Bootstrap template—this IS my personality&lt;br&gt;
Old Meets New: Vintage aesthetics powered by modern engineering&lt;br&gt;
Interactive Storytelling: Your mouse becomes a time machine&lt;/p&gt;

&lt;p&gt;In an era of heavy frameworks and complex UIs, I wanted to strip everything down to the bare metal. My portfolio isn't just a website; it's a homage to the roots of computing—the &lt;strong&gt;Terminal&lt;/strong&gt;. It represents how I work: clean, efficient, and command-driven.&lt;/p&gt;


&lt;h2&gt;
  
  
  🚀 ./deploy_portfolio.sh &amp;gt; The Project
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"Graphic design is the gloss, but the Command Line is the soul."&lt;br&gt;
I built a fully interactive &lt;strong&gt;Terminal Portfolio&lt;/strong&gt; that runs directly in your browser. No buttons, no scroll guessing—just you, the keyboard, and the prompt and if you want the GUI you can access that too.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Try it live here:&lt;/strong&gt; 👇
&lt;/h3&gt;

&lt;p&gt;🚀 &lt;strong&gt;LIVE DEMO&lt;/strong&gt;: Click here to access the terminal](&lt;a href="https://arya-khochare-terminal-portfolio-818474269873.us-central1.run.app" rel="noopener noreferrer"&gt;https://arya-khochare-terminal-portfolio-818474269873.us-central1.run.app&lt;/a&gt;)&lt;/p&gt;


&lt;div class="ltag__cloud-run"&gt;
  &lt;iframe height="600px" src="https://arya-khochare-terminal-portfolio-818474269873.us-central1.run.app"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Pro Tip&lt;/strong&gt;: Type &lt;code&gt;help&lt;/code&gt; in the terminal to unlock all commands! Try &lt;code&gt;gui&lt;/code&gt; for a retro Windows 95-style experience 🪟&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ ./view_source &amp;gt; How I Built It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Philosophy: Going Back to Basics&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In an era of React, Next.js, and complex build pipelines, I asked myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"What if portfolios were reviewed like in the early 2000s—viewed in a terminal, read as plain text files, judged purely on content and creativity?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I built &lt;strong&gt;exactly that&lt;/strong&gt;. A portfolio that &lt;em&gt;embraces constraints&lt;/em&gt; and turns them into &lt;em&gt;features&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I wanted this to feel authentic. No fake static images—this is a living, breathing command line interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  **Tech Stack (Beautifully Simple)
&lt;/h3&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Stack&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: Pure HTML, CSS, and Vanilla JavaScript. No bloat. Fast load times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containerization&lt;/strong&gt;: &lt;strong&gt;Docker&lt;/strong&gt; + &lt;strong&gt;Nginx&lt;/strong&gt; (Alpine) for an ultra-lightweight image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt;: &lt;strong&gt;Google Cloud Run&lt;/strong&gt;. The container scales to zero when not in use, making it efficient and serverless.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Google AI's Role (Antigravity)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This project was accelerated using &lt;strong&gt;Google's Antigravity (AI-first IDE)&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure as Code&lt;/strong&gt;: The AI generated the optimized &lt;code&gt;Dockerfile&lt;/code&gt; and Nginx configuration to make this container production-ready in seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Deployment&lt;/strong&gt;: It guided me through the complex IAM permissions and &lt;code&gt;gcloud&lt;/code&gt; commands to ensure a secure deployment on Cloud Run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code&lt;/strong&gt;: The AI also helped me generate some boilerplate code and also helped me validate my design strategy. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Development Process&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Design Philosophy&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Started with terminal window mockups&lt;/li&gt;
&lt;li&gt;Researched vintage CRT monitor effects&lt;/li&gt;
&lt;li&gt;Studied Matrix (1999) color grading 😎&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Core Features Built&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interactive command-line interface with tab completion&lt;/li&gt;
&lt;li&gt;File system simulation (&lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;pwd&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Command history (↑/↓ arrow keys)&lt;/li&gt;
&lt;li&gt;Easter eggs (try the Konami Code!)&lt;/li&gt;
&lt;li&gt;Dual-mode interface (Terminal + GUI)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Google AI Integration&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Used &lt;strong&gt;Gemini AI&lt;/strong&gt; via AI Studio to:

&lt;ul&gt;
&lt;li&gt;Generate optimized CRT shader effects&lt;/li&gt;
&lt;li&gt;Create responsive layout patterns&lt;/li&gt;
&lt;li&gt;Suggest accessibility improvements&lt;/li&gt;
&lt;li&gt;Debug complex CSS animations&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Antigravity&lt;/strong&gt; for rapid prototyping and deployment testing&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Gemini CLI&lt;/strong&gt; to automate Cloud Run deployment scripts&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎨 Design Decisions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Color Palette&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Inspired by classic terminal emulators:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Primary&lt;/strong&gt;: &lt;code&gt;#00ff41&lt;/code&gt; (Matrix green)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accent&lt;/strong&gt;: &lt;code&gt;#ffb000&lt;/code&gt; (Amber warnings)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Background&lt;/strong&gt;: &lt;code&gt;#0c0c0c&lt;/code&gt; (True black for OLED screens)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error&lt;/strong&gt;: &lt;code&gt;#ff0000&lt;/code&gt; (Classic red alerts)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Typography&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VT323&lt;/strong&gt;: Authentic monospace terminal font&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Font size&lt;/strong&gt;: 20px base (optimized for readability)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Line height&lt;/strong&gt;: 1.4 (terminal-standard)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Animations&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Matrix rain background (opacity: 0.1 for subtlety)&lt;/li&gt;
&lt;li&gt;Blinking cursor (1s interval)&lt;/li&gt;
&lt;li&gt;CRT flicker (0.15s randomized)&lt;/li&gt;
&lt;li&gt;Smooth command input&lt;/li&gt;
&lt;li&gt;Fade-in text reveal&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✨ ./features --verbose &amp;gt; What I'm Most Proud Of
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Authentic Feel&lt;/strong&gt;: The blinking cursor, the typing effect, and the color palette are tuned to feel like a retro CRT monitor.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Easter Eggs&lt;/strong&gt;: Try typing random commands. I've hidden a few surprises for the curious explorers.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Speed&lt;/strong&gt;: Because it's serving static files via Nginx on Cloud Run, it loads instantly.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🤝 Try It Yourself!
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Available Commands:&lt;/strong&gt;&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="nb"&gt;help&lt;/span&gt;          &lt;span class="c"&gt;# View all commands&lt;/span&gt;
about         &lt;span class="c"&gt;# Learn about me&lt;/span&gt;
experience    &lt;span class="c"&gt;# View work history&lt;/span&gt;
skills        &lt;span class="c"&gt;# Check technical skills&lt;/span&gt;
opensource    &lt;span class="c"&gt;# See OSS contributions&lt;/span&gt;
contact       &lt;span class="c"&gt;# Get in touch&lt;/span&gt;
resume        &lt;span class="c"&gt;# Download resume&lt;/span&gt;
gui           &lt;span class="c"&gt;# Switch to GUI mode&lt;/span&gt;
themes        &lt;span class="c"&gt;# List available color themes&lt;/span&gt;
theme &amp;lt;name&amp;gt;  &lt;span class="c"&gt;# Change theme (matrix/amber/hacker/etc.)&lt;/span&gt;
neofetch      &lt;span class="c"&gt;# System info (developer stats)&lt;/span&gt;
clear         &lt;span class="c"&gt;# Clear terminal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Easter Eggs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type &lt;code&gt;sudo rm -rf /&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Explore the GUI mode&lt;/li&gt;
&lt;li&gt;Switch between 7 color themes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏁 exit 0
&lt;/h2&gt;

&lt;p&gt;Building this portfolio reminded me why I fell in love with coding in the first place: the power of typing a command and seeing the machine obey.&lt;br&gt;
It is my digital time machine—a bridge between the terminal-loving hacker I was and the full-stack engineer I've become.&lt;br&gt;
I hope you enjoy exploring my work as much as I enjoyed building this interface.&lt;br&gt;
Happy Coding! 🖖&lt;/p&gt;




&lt;p&gt;⭐ If you enjoyed this nostalgic journey, drop a reaction! Let's bring back the terminal aesthetic! ⭐&lt;/p&gt;

&lt;p&gt;Built with ❤️, ☕, and way too much Matrix nostalgia&lt;/p&gt;

&lt;p&gt;Deployed on Google Cloud Run | Powered by Pure HTML/CSS/JS | Inspired by 1995&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Created for the Dev.to x Google AI Challenge 2026.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  GoogleAI #DevNewYear2026 #RetroWeb #TerminalPortfolio #BackToBasics
&lt;/h1&gt;

</description>
      <category>devchallenge</category>
      <category>googleaichallenge</category>
      <category>portfolio</category>
      <category>gemini</category>
    </item>
    <item>
      <title>Real-Time AI Content Moderation with Redis 8 as Primary Database</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Mon, 11 Aug 2025 06:39:41 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/real-time-ai-content-moderation-with-redis-8-as-primary-database-37jp</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/real-time-ai-content-moderation-with-redis-8-as-primary-database-37jp</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.clauneck.workers.dev/challenges/redis-2025-07-23"&gt;Redis AI Challenge&lt;/a&gt;: Beyond the Cache&lt;/em&gt;.&lt;/p&gt;

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

&lt;p&gt;I created &lt;strong&gt;StreamlinAI&lt;/strong&gt;, a production-ready real-time AI-powered content moderation platform that completely redefines how we think about Redis. Instead of using Redis as just a cache, StreamlinAI leverages &lt;strong&gt;Redis 8 as the primary database, vector search engine, real-time streaming platform, and analytics powerhouse&lt;/strong&gt; - all in one unified system.&lt;/p&gt;

&lt;p&gt;StreamlinAI processes user-generated content in real-time, uses AI for semantic analysis, provides live analytics dashboards, and scales effortlessly - all powered entirely by Redis 8's advanced multi-model capabilities.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;🚀 &lt;a href="https://ai-content-moderation-redis-fronten-five.vercel.app/" rel="noopener noreferrer"&gt;Live Frontend Demo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📚 &lt;a href="https://github.com/Aryakoste/ai-content-moderation-redis" rel="noopener noreferrer"&gt;Complete Source Code&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The live demo showcases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Real-time content processing dashboard&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interactive analytics with live charts&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI-powered content insights panel&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Live activity feed with WebSocket updates&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Responsive design for all devices&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture That Will Blow Your Mind
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   React Frontend │    │  Node.js Backend │   │    Redis 8      │
│                 │    │                 │    │                 │
│ • Live Dashboard│◄──►│ • Express API    │◄──►│ • Streams       │
│ • WebSocket     │    │ • Socket.io      │    │ • Vectors       │
│ • Analytics UI  │    │ • AI Processing  │    │ • TimeSeries    │
│ • Real-time     │    │ • Rate Limiting  │    │ • JSON Docs     │
└─────────────────┘    └─────────────────┘    │ • Pub/Sub       │
                                              │ • Probabilistic │
                                              └─────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How I Used Redis 8
&lt;/h2&gt;

&lt;p&gt;Here's where it gets exciting. I didn't just use Redis 8 for caching - I built the &lt;strong&gt;entire application&lt;/strong&gt; on Redis 8's advanced data structures. Let me show you how each component works:&lt;/p&gt;

&lt;h3&gt;
  
  
  🔄 Redis Streams: The Content Processing Pipeline
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Traditional Approach&lt;/strong&gt;: Queue systems like RabbitMQ or Apache Kafka for message processing.&lt;br&gt;
&lt;strong&gt;StreamlinAI Approach&lt;/strong&gt;: Redis Streams as the primary message processing engine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Content submission flows into Redis Stream&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;streamId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xAdd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content:stream&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;contentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uuidv4&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Consumer groups process content in parallel&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;xReadGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content-processors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;// Consumer group&lt;/span&gt;
  &lt;span class="s2"&gt;`processor-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Consumer name&lt;/span&gt;
  &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content:stream&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;BLOCK&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why This Rocks&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚡ &lt;strong&gt;Fault Tolerance&lt;/strong&gt;: Messages persist until processed&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Scalability&lt;/strong&gt;: Multiple consumer groups for parallel processing&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Monitoring&lt;/strong&gt;: Built-in stream analytics&lt;/li&gt;
&lt;li&gt;🔄 &lt;strong&gt;Replay&lt;/strong&gt;: Reprocess messages from any point&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🧠 Vector Sets: AI-Powered Semantic Search
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Traditional Approach&lt;/strong&gt;: Separate vector databases like Pinecone or Weaviate.&lt;br&gt;
&lt;strong&gt;StreamlinAI Approach&lt;/strong&gt;: Redis 8's native vector search capabilities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Store content with vector embeddings directly in Redis&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`content:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;contentId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;vector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;generateEmbedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;aiAnalysis&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;approved&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;review&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Semantic similarity search in milliseconds&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;similarContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;idx:content_vectors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*=&amp;gt;[KNN 10 @vector $BLOB AS score]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;PARAMS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;BLOB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;queryVector&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;RETURN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;score&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;SORTBY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;BY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;score&lt;/span&gt;&lt;span class="dl"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Magic&lt;/strong&gt;: Redis 8's vector search provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🎯 &lt;strong&gt;Sub-10ms Search&lt;/strong&gt;: Lightning-fast similarity queries&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Hybrid Queries&lt;/strong&gt;: Combine vectors with traditional filters&lt;/li&gt;
&lt;li&gt;📈 &lt;strong&gt;Scalable&lt;/strong&gt;: Handles millions of vectors efficiently&lt;/li&gt;
&lt;li&gt;💾 &lt;strong&gt;Unified Storage&lt;/strong&gt;: Vectors and metadata in same document&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📊 TimeSeries: Real-Time Analytics Engine
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Traditional Approach&lt;/strong&gt;: InfluxDB, Prometheus, or custom time-series solutions.&lt;br&gt;
&lt;strong&gt;StreamlinAI Approach&lt;/strong&gt;: Redis TimeSeries for all metrics and analytics.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Track metrics in real-time&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;metrics:content:processed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;metrics:processing:time&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;processingTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;metrics:accuracy:rate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Query with automatic downsampling&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hourlyMetrics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;metrics:content:processed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;86400000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// 24 hours ago&lt;/span&gt;
  &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;AGGREGATION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sum&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;timeBucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3600000&lt;/span&gt;  &lt;span class="c1"&gt;// 1 hour buckets&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Performance Benefits&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📈 &lt;strong&gt;Compression&lt;/strong&gt;: 94% memory savings with double-delta compression&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;Speed&lt;/strong&gt;: Real-time aggregations without ETL processes&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Retention&lt;/strong&gt;: Automatic data expiration and downsampling&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Built-in Analytics&lt;/strong&gt;: Min, max, avg, count, first, last operations&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📄 JSON Documents: Primary Database Storage
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Traditional Approach&lt;/strong&gt;: MongoDB, PostgreSQL with JSON columns.&lt;br&gt;
&lt;strong&gt;StreamlinAI Approach&lt;/strong&gt;: Redis JSON as the primary database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Complex document storage with JSONPath queries&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`content:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;contentId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;contentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;analysis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;positive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;toxicity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.94&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;excellent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;recommend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;review&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;web&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;processing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sentiment-v2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;accuracy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.94&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;approved&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Advanced JSONPath queries&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;flaggedContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content:*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$[?(@.analysis.toxicity &amp;gt; 0.5)]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📡 Pub/Sub: Real-Time Communication
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Publish processing results instantly&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content:processed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;contentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;approved&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.94&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;processingTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;

&lt;span class="c1"&gt;// WebSocket clients receive updates immediately&lt;/span&gt;
&lt;span class="nx"&gt;subscriber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content:processed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content_update&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Push to frontend&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🎯 Probabilistic Data Structures: Advanced Analytics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Unique visitor counting with HyperLogLog&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pfAdd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visitors:unique&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uniqueVisitors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pfCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visitors:unique&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Duplicate content detection (Bloom filter simulation)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contentHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDuplicate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sIsMember&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content:duplicates&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contentHash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isDuplicate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sAdd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;content:duplicates&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contentHash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Complete Tech Stack
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Frontend&lt;/strong&gt;: React 18, Chart.js, Tailwind CSS, WebSocket client&lt;br&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: Node.js, Express, Socket.io, comprehensive error handling&lt;br&gt;
&lt;strong&gt;Database&lt;/strong&gt;: &lt;strong&gt;100% Redis 8&lt;/strong&gt; - No other databases needed!&lt;br&gt;
&lt;strong&gt;Infrastructure&lt;/strong&gt;: Docker, Nginx, Redis Stack, automated deployment&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance That Speaks Volumes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;⚡ &lt;strong&gt;45ms average processing time&lt;/strong&gt; per content item&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;400+ items/second throughput&lt;/strong&gt; on a single instance
&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;&amp;lt;10ms vector similarity search&lt;/strong&gt; across millions of embeddings&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Real-time analytics&lt;/strong&gt; with &amp;lt;50ms update latency&lt;/li&gt;
&lt;li&gt;💾 &lt;strong&gt;94% memory savings&lt;/strong&gt; with TimeSeries compression&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Production-Ready Features
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Comprehensive API&lt;/strong&gt; with rate limiting and validation&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Real-time WebSocket updates&lt;/strong&gt; for live dashboard&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Docker containerization&lt;/strong&gt; with docker-compose&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Health monitoring&lt;/strong&gt; and error handling&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Security middleware&lt;/strong&gt; with Helmet.js and CORS&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Automated testing&lt;/strong&gt; suite&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Monitoring &amp;amp; observability&lt;/strong&gt; built-in  &lt;/p&gt;

&lt;h2&gt;
  
  
  Key Innovation: The AI Processing Pipeline
&lt;/h2&gt;

&lt;p&gt;The real magic happens in the AI processing pipeline, entirely orchestrated by Redis:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Content Submission&lt;/strong&gt; → Redis Stream (instant queuing)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consumer Groups&lt;/strong&gt; → Parallel AI processing
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vector Storage&lt;/strong&gt; → Semantic embeddings in Redis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics Update&lt;/strong&gt; → TimeSeries metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duplicate Check&lt;/strong&gt; → Probabilistic structures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Notify&lt;/strong&gt; → Pub/Sub to frontend&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard Update&lt;/strong&gt; → WebSocket push&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of this happens in &lt;strong&gt;under 50ms&lt;/strong&gt; with Redis 8 handling every step!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Wins the Challenge
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🎯 Beyond Caching&lt;/strong&gt;: Uses Redis 8 as primary database, not just cache&lt;br&gt;&lt;br&gt;
&lt;strong&gt;🚀 Multi-Model&lt;/strong&gt;: Leverages 6+ different Redis data structures&lt;br&gt;&lt;br&gt;
&lt;strong&gt;⚡ Performance&lt;/strong&gt;: Production-grade speed and scalability&lt;br&gt;&lt;br&gt;
&lt;strong&gt;🏗️ Architecture&lt;/strong&gt;: Clean, modern, well-documented codebase&lt;br&gt;&lt;br&gt;
&lt;strong&gt;🎨 UX&lt;/strong&gt;: Beautiful, responsive real-time interface&lt;br&gt;&lt;br&gt;
&lt;strong&gt;🔒 Production&lt;/strong&gt;: Security, monitoring, Docker deployment  &lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start (2 Commands!)
&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/Aryakoste/ai-content-moderation-redis &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit &lt;code&gt;http://localhost:3000&lt;/code&gt; and watch Redis 8 power everything!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future Is Multi-Model
&lt;/h2&gt;

&lt;p&gt;StreamlinAI proves that &lt;strong&gt;Redis 8 isn't just a cache anymore&lt;/strong&gt; - it's a complete application platform. By combining streams, vectors, time series, JSON documents, pub/sub, and probabilistic structures, we've built something that traditionally would require 5-6 different databases.&lt;/p&gt;

&lt;p&gt;This is the future of application architecture: &lt;strong&gt;unified, fast, and incredibly powerful&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;I'm planning to extend StreamlinAI with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🤖 &lt;strong&gt;Multi-language AI models&lt;/strong&gt; using Redis vector search&lt;/li&gt;
&lt;li&gt;📱 &lt;strong&gt;Mobile app&lt;/strong&gt; with real-time sync
&lt;/li&gt;
&lt;li&gt;🌍 &lt;strong&gt;Multi-tenant support&lt;/strong&gt; using Redis namespacing&lt;/li&gt;
&lt;li&gt;🧠 &lt;strong&gt;Advanced ML pipeline&lt;/strong&gt; with Redis as feature store&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;Kubernetes deployment&lt;/strong&gt; with Redis Enterprise&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It Yourself!
&lt;/h2&gt;

&lt;p&gt;The complete source code is available with comprehensive documentation. Every Redis 8 feature is well-commented and explained.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://ai-content-moderation-redis-fronten-five.vercel.app/" rel="noopener noreferrer"&gt;🚀 Live Demo&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📚 &lt;a href="https://github.com/Aryakoste/ai-content-moderation-redis" rel="noopener noreferrer"&gt;Complete Source Code&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Built with ❤️ and powered entirely by Redis 8&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What will you build beyond the cache? Let me know in the comments!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>redischallenge</category>
      <category>devchallenge</category>
      <category>database</category>
      <category>ai</category>
    </item>
    <item>
      <title>🎯 LiveCaption AI: Real-Time Accessibility Platform with Redis-Powered Intelligence</title>
      <dc:creator>Arya Koste</dc:creator>
      <pubDate>Sun, 10 Aug 2025 21:57:43 +0000</pubDate>
      <link>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/livecaption-ai-real-time-accessibility-platform-with-redis-powered-intelligence-lbp</link>
      <guid>https://dev.clauneck.workers.dev/arya_koste_5845807df94776/livecaption-ai-real-time-accessibility-platform-with-redis-powered-intelligence-lbp</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.clauneck.workers.dev/challenges/redis-2025-07-23"&gt;Redis AI Challenge&lt;/a&gt;: Real-Time AI Innovators&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.clauneck.workers.dev/challenges/redis-2025-07-23"&gt;Redis AI Challenge&lt;/a&gt;: Beyond the Cache&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Imagine joining any conversation — meetings, lectures, or live events — and instantly seeing AI‑powered captions with seamless Q&amp;amp;A support.&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;LiveCaption AI&lt;/strong&gt; makes real‑time, intelligent accessibility possible with &lt;strong&gt;Redis&lt;/strong&gt; powering its lightning‑fast core.&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;p&gt;LiveCaption AI is a revolutionary real-time accessibility platform that transforms audio conversations into live captions, intelligent transcripts, and contextual Q&amp;amp;A responses. Built with Redis as the backbone for ultra-fast real-time data processing, the platform delivers instant audio transcription, semantic caching for AI responses, and live streaming of captions to multiple clients simultaneously.&lt;/p&gt;

&lt;p&gt;With it, anyone — especially hearing-impaired users — can follow conversations in real‑time, ask questions about the conversation history, and receive instant, context‑aware AI answers.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ Key Features:
&lt;/h2&gt;

&lt;p&gt;🎤 Real-Time Audio Transcription - Browser-based speech recognition with Web Speech API&lt;/p&gt;

&lt;p&gt;📡 Live Caption Broadcasting - WebSocket-powered real-time caption streaming to multiple clients&lt;/p&gt;

&lt;p&gt;🧠 Intelligent Q&amp;amp;A System - Context-aware question answering using cached transcripts&lt;/p&gt;

&lt;p&gt;🔄 Smart Caching Layer - Redis-powered semantic caching for AI responses and transcriptions&lt;/p&gt;

&lt;p&gt;📊 Live Analytics Dashboard - Real-time caption statistics and session management&lt;/p&gt;

&lt;p&gt;🌐 Multi-Session Support - Concurrent caption streams for different sessions/rooms&lt;/p&gt;

&lt;p&gt;♿ Accessibility First - Designed for hearing-impaired users and accessibility compliance&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Features and the Redis Technologies Behind Them
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Redis Technology&lt;/th&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🎤 Real-Time Captions&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Redis Streams&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sub‑100 ms real‑time caption delivery to all viewers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;❓ Intelligent Q&amp;amp;A&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Redis JSON + Semantic Cache&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Instant, context‑aware AI answers using cached session data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🔄 Multi-Client Sync&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Redis Pub/Sub&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Real‑time updates and coordination across all connected clients&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;📊 Session Analytics&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Redis JSON + Hash Maps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Live metrics on caption count, confidence, and usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;⚙️ User Preferences&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Redis Hash Maps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Personalized accessibility settings persisted across sessions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Frontend (React): Hosted on Vercel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Backend (Nodejs + Redis): Hosted on Render.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔗 Live demo link: &lt;a href="https://redis-captions-overlay.vercel.app/" rel="noopener noreferrer"&gt;https://redis-captions-overlay.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 Github link: &lt;a href="https://github.com/Aryakoste/redis-captions-overlay" rel="noopener noreferrer"&gt;https://github.com/Aryakoste/redis-captions-overlay&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📌 Note:&lt;br&gt;
The live version on Render free tier does not include live Python LLM + transcription workers due to service type restrictions and free tier plan.&lt;br&gt;
When run locally, all features including full Q&amp;amp;A and advanced transcription work flawlessly. I have shared below screenshots.&lt;/p&gt;
&lt;h2&gt;
  
  
  📷 Screenshots
&lt;/h2&gt;

&lt;p&gt;1) 🟢 Live Real-Time Caption Display&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.amazonaws.com%2Fuploads%2Farticles%2F1ivpl3klxd99h62c4fsj.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.amazonaws.com%2Fuploads%2Farticles%2F1ivpl3klxd99h62c4fsj.png" alt="Real-Time Captions" width="800" height="358"&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2F0tpy2erxbol83xh5deos.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.amazonaws.com%2Fuploads%2Farticles%2F0tpy2erxbol83xh5deos.png" alt="Live Captions" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2) ❓ Intelligent Q&amp;amp;A System&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.amazonaws.com%2Fuploads%2Farticles%2Feb0n25hnw7qqkhzhfuqb.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.amazonaws.com%2Fuploads%2Farticles%2Feb0n25hnw7qqkhzhfuqb.png" alt="Qna AI" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3) 📊 Session Analytics Dashboard&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.amazonaws.com%2Fuploads%2Farticles%2Fj0d6f2k0vxojzdgebsgk.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.amazonaws.com%2Fuploads%2Farticles%2Fj0d6f2k0vxojzdgebsgk.png" alt="Dashboard" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4) 🔍 Transcripts Search&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.amazonaws.com%2Fuploads%2Farticles%2F1n761smcs5xipqwarvjm.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.amazonaws.com%2Fuploads%2Farticles%2F1n761smcs5xipqwarvjm.png" alt="Transcripts Search" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5) 📝 Audio Recorder and File Uploader&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.amazonaws.com%2Fuploads%2Farticles%2Fr6igl6426kjbls9tvym0.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.amazonaws.com%2Fuploads%2Farticles%2Fr6igl6426kjbls9tvym0.png" alt="Audio Recorder" width="800" height="348"&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2Flte5oydjhttcbx99qga9.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.amazonaws.com%2Fuploads%2Farticles%2Flte5oydjhttcbx99qga9.png" alt="File Uploader" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;6) 🔍 Captions/Knowledge Base Search&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.amazonaws.com%2Fuploads%2Farticles%2Fiublrugmcxwtkgcdhyyi.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.amazonaws.com%2Fuploads%2Farticles%2Fiublrugmcxwtkgcdhyyi.png" alt="Knowledge Base Search" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  ⚙️How I Used Redis as My Real-Time Data Layer
&lt;/h2&gt;

&lt;p&gt;Redis 8 is central for this project:&lt;/p&gt;

&lt;p&gt;🎯 1. Redis Streams for Real-Time Caption Broadcasting&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await redis.xAdd('captions:stream', '*', {
  text: transcription.text,
  session_id: sessionId,
  timestamp: Date.now(),
  confidence: transcription.confidence,
  language: transcription.language
});
const messages = await redis.xRead(
  { key: 'captions:stream', id: '$' }, 
  { BLOCK: 0 }
);

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

&lt;/div&gt;



&lt;p&gt;⚡ 2. Semantic Caching for AI Response Optimization&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const cacheKey = `ai_cache:llm:${crypto.createHash('sha256')
  .update(question + context).digest('hex')}`;
const cached = await redis.get(cacheKey);
if (cached) return JSON.parse(cached);
await redis.setEx(cacheKey, 7200, JSON.stringify(aiResponse));

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

&lt;/div&gt;



&lt;p&gt;📊 3. Redis JSON for Session Management &amp;amp; Analytics&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await redis.json.set(`session:${sessionId}`, '$', {
  id: sessionId,
  startTime: Date.now(),
  captionCount: 0,
  analytics: { totalWords: 0, avgConfidence: 0 }
});
await redis.json.numIncrBy(`session:${sessionId}`, '$.captionCount`, 1);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔍 4. Pub/Sub for Multi-Client Synchronization&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await redis.publish(`captions:${sessionId}`, JSON.stringify({
  type: 'new_caption',
  data: captionData
}));
redis.subscribe(`captions:${sessionId}`, (message) =&amp;gt; {
  broadcastToClients(message);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💾 5. Redis Hash Maps for User Preferences&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;await redis.hSet(`user:${userId}:prefs`, {
  fontSize: 'large', contrast: 'high', language: 'en-US'
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📈 Performance Metrics
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Caption Latency&lt;/td&gt;
&lt;td&gt;&amp;lt;100 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Cache Hit Rate&lt;/td&gt;
&lt;td&gt;85 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concurrent Users Tested&lt;/td&gt;
&lt;td&gt;500+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WebSocket Connections&lt;/td&gt;
&lt;td&gt;1 000+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redis Memory Usage&lt;/td&gt;
&lt;td&gt;&amp;lt;50 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transcription Accuracy&lt;/td&gt;
&lt;td&gt;95 %+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🛠 Architecture &amp;amp; Technical Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Backend (Node.js + Express) – Real-time WebSocket server, REST API, Redis integration&lt;/li&gt;
&lt;li&gt;Python Worker – LLM Q&amp;amp;A and audio transcription jobs via Redis streams&lt;/li&gt;
&lt;li&gt;Frontend (React) – Web Speech API for browser transcription, WebSocket client, accessibility-first UI&lt;/li&gt;
&lt;li&gt;Redis Features – Streams, JSON, Pub/Sub, Caching, Hash Maps&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌟 Innovation Highlights
&lt;/h2&gt;

&lt;p&gt;🚀 Ultra-Fast AI Response Caching – Reduces AI response time by 98% (3s → 50ms)&lt;/p&gt;

&lt;p&gt;📡 Real-Time Multi-Client Broadcasting – Sub-100ms latency for hundreds of users&lt;/p&gt;

&lt;p&gt;🧠 Context-Aware Intelligence – Maintains conversation context via Redis JSON&lt;/p&gt;

&lt;p&gt;♿ Accessibility-First Design – High-contrast themes, keyboard navigation, screen reader support&lt;/p&gt;




&lt;h2&gt;
  
  
  🔮 Future Enhancements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt; Vector Search for semantic caption search&lt;/li&gt;
&lt;li&gt; Real-time Translation with Redis-cached models&lt;/li&gt;
&lt;li&gt; Voice Biometrics for speaker identification&lt;/li&gt;
&lt;li&gt; Video conferencing platform integrations&lt;/li&gt;
&lt;li&gt; Offline-capable mobile app&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Thank you Redis and DEV for this challenge!&lt;br&gt;
Making AI-powered accessibility real-time, open, and scalable.&lt;/p&gt;

&lt;p&gt;Tags: #RedisAI #RealTime #Accessibility #WebSockets #AI #React #NodeJS &lt;/p&gt;

</description>
      <category>redischallenge</category>
      <category>devchallenge</category>
      <category>database</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
