How I Built a Review Site with 800+ Articles Using AI

How I Built a Review Site with 800+ Articles Using AI

The stack, the workflow, and what actually worked

A few months ago, I wanted to build a review site for Chinese consumer brands — products like GaN chargers, USB-C hubs, smart home devices, and laptops that are popular in Asia but don’t get much coverage in English-language tech blogs.

The goal was simple: produce useful, data-driven reviews at scale. No clickbait, no affiliate-first garbage. Just honest comparisons with real specs and real user feedback.

Here’s how I built it, what the workflow looks like, and what I learned along the way.

1. The Stack

The site runs on a minimal stack:

  • Next.js (static export) — fast builds, great DX
  • Decap CMS — Git-based CMS so editors don’t need a database
  • Vercel — free hosting, instant rollbacks
  • GitHub — content and code in one repo

No backend to manage. Every article is a Markdown file in the repo. Decap CMS gives the content team a nice UI on top, but the source of truth is Git.

2. Why AI for Content?

I didn’t want to build yet another AI-generated content mill. The approach was different:

  • Research first: AI gathers product specs, pricing, and real user reviews from multiple sources
  • Human structure: Each article follows a template (overview → specs → performance → real user feedback → verdict)
  • Data verification: Pricing and specs are checked against official sources before publishing
  • Images are real: No AI-generated product images. Every photo comes from official brand sites or verified listings

The AI handles the heavy lifting — research, formatting, translation of Chinese reviews — while humans control the quality bar.

3. The Content Pipeline

Here’s the actual workflow for each article:

  1. Product selection — Identify trending products on JD.com, Taobao, and Tmall
  2. Spec collection — Pull official specs from brand sites and verified product pages
  3. User review aggregation — Collect real buyer feedback (good and bad) from verified purchasers
  4. Article generation — Structure everything into a consistent, readable format
  5. Review pass — Check all specs against official sources, verify pricing, remove any hallucinated claims
  6. Image sourcing — Download official product images from brand sites (no guessing CDN URLs)
  7. Publish — Commit to Git, Vercel deploys automatically

4. What Actually Worked

✓ Real data beats SEO tricks

The articles that perform best aren’t the ones with keyword-stuffed titles. They’re the ones with actual benchmarks and real user experiences. A USB-C cable buying guide with measured charging speeds and compatibility testing gets more engagement than any generic listicle.

✓ Consistency matters more than perfection

Publishing 3-5 articles daily (focused, well-researched ones) built organic traffic faster than trying to write one perfect article per week. Search engines reward freshness.

✓ User reviews are gold

Chinese e-commerce platforms have incredibly detailed review systems, often with photos. Translating and aggregating authentic user feedback gives articles depth that pure spec sheets can’t match.

5. What Didn’t Work

✗ Pure AI generation

Early tests with full AI generation produced articles that looked good but lacked depth. They’d say “great product” without explaining why. The fix was adding real user quotes and verified test data.

✗ Guessing CDN image URLs

We tried building an automated image pipeline using pattern-matched CDN URLs. It failed constantly. The solution was going back to sourcing images manually from official brand sites.

✗ Over-optimizing for search

The first batch of articles tried too hard to match search patterns. They read like SEO sludge. The fix was writing for humans first and treating keywords as a secondary concern.

6. Numbers After 800 Articles

  • 800+ published articles across 19 categories
  • 100% real product images (every article has at least one genuine photo)
  • Organic traffic growing steadily since launch
  • AdSense approved and running

Not explosive growth, but steady, sustainable progress.

7. Key Takeaways

  1. AI is a multiplier, not a replacement — The best results come from AI handling research and structure while humans handle verification
  2. Content quality is a flywheel — Good content attracts better readers, which attracts better engagement, which signals quality to search engines
  3. Don’t skip the boring parts — Checking specs against official sources, sourcing real images, and verifying user reviews takes time but builds trust
  4. Ship fast, iterate faster — Get the first 50 articles up, then improve based on what the data tells you

If you’re building something similar or have questions about the workflow, drop a comment below. Happy to share more details about specific parts of the pipeline.

I Built a Smart Kitchen AI with Gemma 4 That Turns Fridge Photos Into Recipes

This is a submission for the Gemma 4 Challenge: Build with Gemma 4

I Built a Smart Kitchen AI with Gemma 4 That Turns Fridge Photos Into Recipes

What I Built

Smart Kitchen AI is a multimodal AI-powered cooking assistant designed to make everyday cooking smarter and easier.

The idea started during a Build With AI bootcamp where my team and I wanted to explore how AI could solve practical real-world problems using computer vision and intelligent reasoning.

The workflow is simple:

  1. Users upload a photo of ingredients available in their refrigerator
  2. The AI analyzes the visible ingredients
  3. It generates recipe suggestions based on the detected items
  4. The system can also recommend possible meal ideas and smart combinations

The goal was to create an AI experience that feels genuinely useful in daily life instead of just being another chatbot demo.

Demo

Core Features

  • Fridge image analysis
  • Ingredient detection
  • AI-powered recipe generation
  • Smart meal suggestions
  • Multimodal AI interaction
  • Modern user-friendly interface

Example Workflow

Upload refrigerator image ➜ AI detects ingredients ➜ Smart recipes generated instantly

Future Improvements

  • Nutrition analysis
  • Grocery recommendations
  • Voice assistant integration
  • Personalized meal planning
  • Smart kitchen automation

Code

Technologies Used

  • Python
  • Flask
  • HTML/CSS
  • AI image analysis workflows
  • Prompt engineering
  • Gemma 4 integration concepts

GitHub Repository

https://github.com/rishihuyr

How I Used Gemma 4

For this project, I explored the potential of Gemma 4 multimodal capabilities to power intelligent recipe understanding and contextual reasoning.

I chose the Gemma 4 31B Dense model because the project required:

  • stronger reasoning,
  • multimodal understanding,
  • and better contextual response generation.

Since Smart Kitchen AI needs to understand ingredient combinations and generate meaningful cooking suggestions, a more capable reasoning-focused model made the most sense for the experience I wanted to create.

What impressed me most about Gemma 4 was the balance between:

  • reasoning capabilities,
  • multimodal potential,
  • and flexible deployment possibilities.

Instead of building a generic AI chatbot, I wanted to create something practical that demonstrates how multimodal AI can improve everyday experiences.

That’s what made Gemma 4 such an exciting fit for this project.

Challenges I Faced

One of the biggest challenges was designing prompts and workflows that generated useful recipe recommendations instead of random outputs.

Ingredient recognition can also become difficult when refrigerator images contain:

  • unclear lighting,
  • overlapping objects,
  • or partially visible ingredients.

Improving contextual understanding and response quality became an important part of the experimentation process.

What I Learned

This project taught me that some of the most exciting AI ideas are often the simplest ones.

Not every AI application needs to be futuristic or overly complex.

Sometimes solving small real-world problems in a smart and accessible way can create the best user experiences.

Building Smart Kitchen AI also helped me better understand:

  • multimodal AI workflows,
  • prompt engineering,
  • AI reasoning systems,
  • and how modern open models like Gemma 4 can support practical innovation.

Final Thoughts

AI is slowly becoming part of everyday life.

Projects like Smart Kitchen AI made me realize that multimodal models are opening the door to a future where AI can understand images, context, and human intent more naturally than ever before.

And honestly, that future feels incredibly exciting.

Tags

devchallenge #gemmachallenge #gemma #ai

Why your vulnerability dashboard is lying to you (and how to fix it)

You open your vulnerability dashboard on a Monday morning and see 47 critical CVEs
across 12 assets. By Thursday, your team has patched 11 of the 12 assets. But the
dashboard still shows 40 criticals. What happened?

The assets were patched. The dashboard doesn’t know that, because the vulnerability
scanner sees a different record than the asset your team was tracking. The same
physical server exists in your tools as:

Tool Identifier
AWS i-0a1b2c3d4e5f
CrowdStrike prod-api-07.internal
Tenable 10.0.4.22 (scan-time IP)
Qualys 10.0.4.23 (different scan window, NATted)

When Tenable reports the CVE patched on 10.0.4.22, your dashboard doesn’t
automatically know that 10.0.4.22 is the same machine as prod-api-07.internal.
So it still shows the finding as open on the CrowdStrike record.

This is the asset identity problem. Most security teams have it. Almost nobody
talks about it.

The standard approaches — and why they fall short

“We use the hostname” — Hostnames are normalized differently by every tool.
Tenable might see prod-api-07, CrowdStrike sees prod-api-07.internal,
ServiceNow has PRODAPI007 from a manual entry made 8 months ago.

“We use the IP address” — IPs change. NAT means the scanner sees a different
IP than the one the EDR agent reports. A host that was 10.0.4.22 last week might
be 10.0.4.31 today.

“We have a CMDB” — Great, how fresh is it? Most CMDBs are 30–60% stale within
6 months of implementation. And you still need to write the correlation logic to
feed it.

A layered matching approach

The core insight is that no single identifier is reliable across tools, but
combining multiple identifiers with explicit confidence scoring gets you very far.

Here’s the priority order:

Layer 1 — Hard IDs (confidence: 0.95–1.0)

Match on instanceId, EDR agentId, or MAC address. These are tool-native stable
identifiers. If two records share a hard ID, they’re the same asset with near-certainty.

Layer 2 — Hostname (confidence: 0.45–0.85)

Normalize first: strip .local, .internal, case-fold, drop -prod/-dev
suffixes. Then match. Confidence scales with how unique the hostname looks.

Layer 3 — IP address (confidence: 0.60–0.75)

Public IPs get higher confidence than private IPs. Apply a staleness decay: an IP
seen 30 days ago is worth less than one seen yesterday. Private IPs in NAT-heavy
environments are unreliable and scored conservatively.

Layer 4 — Metadata (confidence: up to 0.50)

OS family + cloud region + account ID. Useful as a tie-breaker. Not enough alone.

Combine layers 2 and 3: 0.60 × hostname_score + 0.40 × ip_score. Merge if the
composite score is ≥ 0.70. Flag for human review if 0.50–0.69. Create a new
canonical record if < 0.50.

The key design principle: ambiguous matches are never silently merged. A 50%
confident merge creates ghost duplicates that are worse than no merge at all.

Building the canonical record

Once you’ve matched records, you merge them. But “merge” has a lot of edge cases:

  • Which hostname wins when AWS says prod-api-07 and the EDR says prod-api-07.internal?
    Answer: EDR is more authoritative for hostnames; AWS is more authoritative for region.
  • What about IP addresses? Union them — an asset can have both a private and public IP.
  • What if two sources report different OS names? Log the conflict with both values,
    both sources, and the resolution taken.

Every field disagreement should be logged with full lineage. Conflicts are data.

The open-source implementation

I’ve been writing this glue layer at multiple companies. Last week I open-sourced it.


bash
pip install security-asset-correlator
https://github.com/apurvtyagi/security-asset-correlator

Why your vulnerability dashboard is lying to you (and how to fix it)

You open your vulnerability dashboard on a Monday morning and see 47 critical CVEs
across 12 assets. By Thursday, your team has patched 11 of the 12 assets. But the
dashboard still shows 40 criticals. What happened?

The assets were patched. The dashboard doesn’t know that, because the vulnerability
scanner sees a different record than the asset your team was tracking. The same
physical server exists in your tools as:

Tool Identifier
AWS i-0a1b2c3d4e5f
CrowdStrike prod-api-07.internal
Tenable 10.0.4.22 (scan-time IP)
Qualys 10.0.4.23 (different scan window, NATted)

When Tenable reports the CVE patched on 10.0.4.22, your dashboard doesn’t
automatically know that 10.0.4.22 is the same machine as prod-api-07.internal.
So it still shows the finding as open on the CrowdStrike record.

This is the asset identity problem. Most security teams have it. Almost nobody
talks about it.

The standard approaches — and why they fall short

“We use the hostname” — Hostnames are normalized differently by every tool.
Tenable might see prod-api-07, CrowdStrike sees prod-api-07.internal,
ServiceNow has PRODAPI007 from a manual entry made 8 months ago.

“We use the IP address” — IPs change. NAT means the scanner sees a different
IP than the one the EDR agent reports. A host that was 10.0.4.22 last week might
be 10.0.4.31 today.

“We have a CMDB” — Great, how fresh is it? Most CMDBs are 30–60% stale within
6 months of implementation. And you still need to write the correlation logic to
feed it.

A layered matching approach

The core insight is that no single identifier is reliable across tools, but
combining multiple identifiers with explicit confidence scoring gets you very far.

Here’s the priority order:

Layer 1 — Hard IDs (confidence: 0.95–1.0)

Match on instanceId, EDR agentId, or MAC address. These are tool-native stable
identifiers. If two records share a hard ID, they’re the same asset with near-certainty.

Layer 2 — Hostname (confidence: 0.45–0.85)

Normalize first: strip .local, .internal, case-fold, drop -prod/-dev
suffixes. Then match. Confidence scales with how unique the hostname looks.

Layer 3 — IP address (confidence: 0.60–0.75)

Public IPs get higher confidence than private IPs. Apply a staleness decay: an IP
seen 30 days ago is worth less than one seen yesterday. Private IPs in NAT-heavy
environments are unreliable and scored conservatively.

Layer 4 — Metadata (confidence: up to 0.50)

OS family + cloud region + account ID. Useful as a tie-breaker. Not enough alone.

Combine layers 2 and 3: 0.60 × hostname_score + 0.40 × ip_score. Merge if the
composite score is ≥ 0.70. Flag for human review if 0.50–0.69. Create a new
canonical record if < 0.50.

The key design principle: ambiguous matches are never silently merged. A 50%
confident merge creates ghost duplicates that are worse than no merge at all.

Building the canonical record

Once you’ve matched records, you merge them. But “merge” has a lot of edge cases:

  • Which hostname wins when AWS says prod-api-07 and the EDR says prod-api-07.internal?
    Answer: EDR is more authoritative for hostnames; AWS is more authoritative for region.
  • What about IP addresses? Union them — an asset can have both a private and public IP.
  • What if two sources report different OS names? Log the conflict with both values,
    both sources, and the resolution taken.

Every field disagreement should be logged with full lineage. Conflicts are data.

The open-source implementation

I’ve been writing this glue layer at multiple companies. Last week I open-sourced it.


bash
pip install security-asset-correlator
https://github.com/apurvtyagi/security-asset-correlator

From Abandoned Prototype to Smart AI System: Reviving Trafiq AI with GitHub Copilot

Trafiq AI Dashboard

This is a submission for the GitHub Finish-Up-A-Thon Challenge

I Revived My Abandoned AI Traffic Project Using GitHub Copilot — And It Became Better Than I Imagined

What I Built

Trafiq AI is a smart AI-powered traffic management concept focused on improving how future smart cities analyze and manage traffic systems.

The idea originally started during an innovation-focused project where I wanted to explore how AI could help:

  • detect traffic congestion,
  • optimize routes,
  • analyze traffic flow,
  • and improve smart transportation systems.

At the beginning, Trafiq AI was mostly a rough prototype with incomplete ideas, unfinished UI screens, and limited functionality.

But instead of letting the project stay abandoned, I decided to bring it back and completely rethink the experience.

This challenge became the perfect reason to finally finish what I started.

Demo

Core Features

  • AI-powered traffic analysis
  • Smart route optimization concepts
  • Traffic heatmap visualization
  • Predictive traffic insights
  • Futuristic dashboard UI
  • Smart city inspired interface

Project Screenshots

Trafiq AI Dashboard

Trafiq AI Workspace

Vision

The long-term vision behind Trafiq AI is to explore how AI systems can support:

  • smarter transportation,
  • intelligent city planning,
  • and future smart city ecosystems.

The Comeback Story

Like many hackathon-style projects, Trafiq AI started with excitement but eventually got pushed aside.

The biggest problems were:

  • incomplete implementation,
  • lack of polish,
  • unfinished UI,
  • and limited time during development.

At one point, the project became just another unfinished idea sitting in my folders.

But revisiting the project later felt completely different.

Instead of simply fixing bugs, I focused on transforming the project into something more realistic and visually polished.

Here’s what changed during the revival process:

Before

  • Basic prototype
  • Unfinished dashboard
  • Rough UI design
  • Limited traffic visualization
  • Incomplete project structure

After

  • Futuristic smart-city inspired interface
  • Improved dashboard experience
  • Better visual presentation
  • Cleaner structure and organization
  • Expanded AI-driven concepts and workflows

One thing I realized during this process is that unfinished projects often still contain strong ideas.

Sometimes they just need more time, patience, and better tools.

My Experience with GitHub Copilot

GitHub Copilot genuinely helped speed up the rebuilding process.

While working on Trafiq AI, Copilot helped me with:

  • code suggestions,
  • debugging support,
  • UI improvements,
  • faster implementation,
  • and organizing repetitive logic.

What I liked most was how it reduced development friction during experimentation.

Instead of getting stuck repeatedly searching for small syntax fixes or boilerplate code, I could focus more on improving the actual project experience and exploring ideas faster.

As someone still learning and building projects in the AI space, that productivity boost felt extremely valuable.

What I Learned

Reviving an abandoned project taught me something important:

A project doesn’t need to start perfectly to become meaningful.

Many student projects fail not because the idea is bad, but because time, polish, and consistency become difficult during fast-paced development.

This challenge pushed me to revisit an unfinished idea and turn it into something I’m genuinely proud of.

And honestly, seeing an old prototype evolve into a much more polished AI concept felt incredibly satisfying.

Final Thoughts

AI and smart systems are changing how we imagine future cities, automation, and real-world problem solving.

Trafiq AI started as a simple experimental idea.

But rebuilding it with better tools, improved design thinking, and support from GitHub Copilot showed me how much unfinished projects can still evolve.

This challenge wasn’t just about finishing code.

It was about finishing something I once believed had potential.

And I’m really glad I came back to it.

Tags

devchallenge #githubchallenge #github #ai

From Abandoned Prototype to Smart AI System: Reviving Trafiq AI with GitHub Copilot

Trafiq AI Dashboard

This is a submission for the GitHub Finish-Up-A-Thon Challenge

I Revived My Abandoned AI Traffic Project Using GitHub Copilot — And It Became Better Than I Imagined

What I Built

Trafiq AI is a smart AI-powered traffic management concept focused on improving how future smart cities analyze and manage traffic systems.

The idea originally started during an innovation-focused project where I wanted to explore how AI could help:

  • detect traffic congestion,
  • optimize routes,
  • analyze traffic flow,
  • and improve smart transportation systems.

At the beginning, Trafiq AI was mostly a rough prototype with incomplete ideas, unfinished UI screens, and limited functionality.

But instead of letting the project stay abandoned, I decided to bring it back and completely rethink the experience.

This challenge became the perfect reason to finally finish what I started.

Demo

Core Features

  • AI-powered traffic analysis
  • Smart route optimization concepts
  • Traffic heatmap visualization
  • Predictive traffic insights
  • Futuristic dashboard UI
  • Smart city inspired interface

Project Screenshots

Trafiq AI Dashboard

Trafiq AI Workspace

Vision

The long-term vision behind Trafiq AI is to explore how AI systems can support:

  • smarter transportation,
  • intelligent city planning,
  • and future smart city ecosystems.

The Comeback Story

Like many hackathon-style projects, Trafiq AI started with excitement but eventually got pushed aside.

The biggest problems were:

  • incomplete implementation,
  • lack of polish,
  • unfinished UI,
  • and limited time during development.

At one point, the project became just another unfinished idea sitting in my folders.

But revisiting the project later felt completely different.

Instead of simply fixing bugs, I focused on transforming the project into something more realistic and visually polished.

Here’s what changed during the revival process:

Before

  • Basic prototype
  • Unfinished dashboard
  • Rough UI design
  • Limited traffic visualization
  • Incomplete project structure

After

  • Futuristic smart-city inspired interface
  • Improved dashboard experience
  • Better visual presentation
  • Cleaner structure and organization
  • Expanded AI-driven concepts and workflows

One thing I realized during this process is that unfinished projects often still contain strong ideas.

Sometimes they just need more time, patience, and better tools.

My Experience with GitHub Copilot

GitHub Copilot genuinely helped speed up the rebuilding process.

While working on Trafiq AI, Copilot helped me with:

  • code suggestions,
  • debugging support,
  • UI improvements,
  • faster implementation,
  • and organizing repetitive logic.

What I liked most was how it reduced development friction during experimentation.

Instead of getting stuck repeatedly searching for small syntax fixes or boilerplate code, I could focus more on improving the actual project experience and exploring ideas faster.

As someone still learning and building projects in the AI space, that productivity boost felt extremely valuable.

What I Learned

Reviving an abandoned project taught me something important:

A project doesn’t need to start perfectly to become meaningful.

Many student projects fail not because the idea is bad, but because time, polish, and consistency become difficult during fast-paced development.

This challenge pushed me to revisit an unfinished idea and turn it into something I’m genuinely proud of.

And honestly, seeing an old prototype evolve into a much more polished AI concept felt incredibly satisfying.

Final Thoughts

AI and smart systems are changing how we imagine future cities, automation, and real-world problem solving.

Trafiq AI started as a simple experimental idea.

But rebuilding it with better tools, improved design thinking, and support from GitHub Copilot showed me how much unfinished projects can still evolve.

This challenge wasn’t just about finishing code.

It was about finishing something I once believed had potential.

And I’m really glad I came back to it.

Tags

devchallenge #githubchallenge #github #ai

Why Country/State/City Pickers Are Weirdly Hard

Country state city picker

Every time I see this on a wireframe, I lie to myself.

“Yeah, that’s easy.”

Three dropdowns. Country → State → City.

Then three days disappear.

Country state city picker

It starts innocent

Select a country, load states, select a state, load cities.

Then: Singapore has no states. Some countries call them provinces. Some APIs return empty arrays. A handful aren’t in the dataset at all depending on which source you’re pulling from.

Product wants search because nobody scrolls 195 countries on mobile. Then keyboard nav. Loading states. Error handling for when the city call fails mid-form. Caching so you’re not hammering the API on every keystroke.

None of it is hard. It just keeps accumulating. By the third project you’re copy-pasting code from your last one and hoping nothing changed. By the fifth you’re a little angry.

The data is the actual problem

Country and city names feel stable until you work with them. Turkey officially became Türkiye in 2022. Cities get renamed. The Philippines has over 1,600 municipalities and that number moves. Some datasets recognize Kosovo. Others don’t.

Most npm packages I tried were one of two things: a component sitting on a JSON file nobody had touched in two years, or solid current data with no UI layer at all.

Five rebuilds in, I stopped pretending this was handled.

What I built

I built react-country-state-city-picker.

Cascading logic, search, loading states, countries without states, keyboard nav, caching, dark/light mode. There’s a single <CountryStateCityPicker> if you want the whole thing wired up, individual pickers if you only need one level, and headless hooks if you want your own UI. No dependencies outside React 18.

I wasn’t trying to build something clever. I wanted a picker I could install and not think about again.

Quick start

npm install react-country-state-city-picker
import { CountryStateCityPicker } from 'react-country-state-city-picker'

function ShippingForm() {
  return (
    <CountryStateCityPicker
      onCountryChange={(country) => console.log(country)}
      onStateChange={(state) => console.log(state)}
      onCityChange={(city) => console.log(city)}
    />
  )
}

That’s the basic setup. Individual pickers and custom render props are there if you need them.

Try it

MIT licensed, on GitHub: react-country-state-city-picker

If you’ve rebuilt this before, you know what it’s worth.

Originally published at shankulkarni.com

Node.js 22 LTS — EOL Date, Support Timeline, and What Comes Next

Node.js 22 became Active LTS in October 2024. That sounds recent. It isn’t.

Active LTS means the clock is already running. Node.js 22 reaches End of Life on April 30, 2027 — less than two years from now. And if the pattern from Node 16, 18, and 20 holds, a significant chunk of production environments will still be running it six months after that date.

This article covers the full Node.js 22 support timeline, how it fits into the broader release schedule, what the EOL Risk Score looks like today versus in 2027, and what your team should be planning now.

The Node.js 22 LTS Timeline

Phase Start End
Current (odd release) April 2024 October 2024
Active LTS October 2024 October 2026
Maintenance LTS October 2026 April 30, 2027
End of Life April 30, 2027 —

Node.js follows a predictable release cadence: even-numbered versions become LTS, odd-numbered versions don’t. Node.js 22 is even, so it gets the full LTS treatment — Active LTS for two years, then Maintenance for six months, then EOL.

The Maintenance phase is the one most teams miss. After October 2026, Node.js 22 only receives critical bug fixes and security patches — no new features, no non-critical fixes. If you’re still on Node 22 in early 2027, you’re already in a degraded support window before you even hit EOL.

Where Node.js 22 Fits in the Full Release Schedule

Here’s the full picture as of May 2026:

Version Status EOL Date EOL Risk Score
Node.js 14 EOL April 30, 2023 95 Critical
Node.js 16 EOL September 11, 2023 90 Critical
Node.js 18 EOL April 30, 2025 85 Critical
Node.js 20 EOL April 30, 2026 76 Critical
Node.js 22 Active LTS April 30, 2027 50 Medium
Node.js 24 Current April 30, 2028 30 Low

Node.js 20 just hit EOL on April 30, 2026 — less than a month ago. If your team is running Node 20 in production today, you’re already in the same position teams were in with Node 18 a year ago.

Node.js 22’s current EOL Risk Score is 50 Medium — it’s supported, but the attack surface score (30/30) is already baked in because Node.js is a high-exposure runtime regardless of support status. That score climbs to Critical the moment it hits EOL in April 2027.

What the Score Looks Like Today vs. April 2027

The EOL Risk Score™ on endoflife.ai breaks down like this for Node.js 22 today:

Factor Score Max Notes
EOL Recency 0 40 Currently supported — zero penalty
Attack Surface 30 30 High-exposure runtime, always maxed
CISA KEV Exposure 20 20 Node ecosystem has known exploited vulns
Extended Support 0 10 No extended support available yet
Total 50 100 Medium

The day Node.js 22 hits EOL on April 30, 2027, the Recency score jumps from 0 to 40. Total score: 90 Critical. Nothing about your infrastructure changes — just the date.

That’s the EOL cliff. Teams that plan migrations 6-12 months in advance avoid it. Teams that don’t end up running Critical-rated software in production while scrambling to upgrade.

The Pattern: What History Tells Us

Node.js 18 hit EOL on April 30, 2025. Based on download and deployment data, a significant portion of Node.js production workloads were still on Node 18 six months later. The same pattern played out with Node 16 and Node 14 before it.

Why does this keep happening?

  • Upgrade friction is real. Dependency trees, native modules, and CI/CD pipeline compatibility all need testing.
  • EOL dates feel abstract. April 2027 sounds far away in May 2026.
  • Prioritization is hard. “It still works” wins most sprint planning arguments.

The teams that handle this well aren’t faster — they just start earlier. If you’re reading this in May 2026, you have 23 months before Node 22 EOL. That’s comfortable. If you’re reading this in January 2027, you have 3 months. That’s a fire drill.

Node.js 22 Key Features Worth Knowing

Before you start planning the migration to Node 24, know what you’re on:

  • V8 12.4 — improved performance, better WebAssembly support
  • Native test runner stabilized — node:test is production-ready
  • require() for ES modules — experimental but significant for ecosystem compatibility
  • WebSocket client — built-in, no ws dependency needed for basic use cases
  • Maglev compiler — faster startup times, better JIT performance

Node.js 22 is a genuinely good release. That’s exactly why it’ll still be running in production in 2028 at companies that didn’t plan ahead.

What to Do Now

If you’re on Node 18 or 20: You’re already past EOL or just hit it. This is urgent. Check your EOL Risk Score at endoflife.ai/nodejs/18 or endoflife.ai/nodejs/20.

If you’re on Node 22: You have runway. Use it. Schedule the Node 24 migration for Q1 2027 at the latest — that gives you a 3-month buffer before EOL and keeps you out of the Maintenance-only window.

If you’re on Node 24: You’re current. Node 24 EOL is April 2028. Check back in 18 months.

Scan your full stack: Node version is one data point. The underlying OS, runtime dependencies, and framework versions all have their own EOL dates. Use the Stack Scanner at endoflife.ai to get the full picture.

Check Your Node.js Version Score

Every Node.js version has a dedicated score card on endoflife.ai:

EOL Risk Score™ is a proprietary methodology developed by endoflife.ai. Scores are calculated at build time from four factors: EOL Recency, Attack Surface, CISA KEV Exposure, and Extended Support Availability.

Part of The EOL Intelligence Report series on DEV.to.

The 7-Layer Memory Architecture Behind Modern AI Agents

ai memory

How do you make an AI agent actually remember?

ai memory

It is the question that inevitably surfaces once an AI system moves out of prototyping and into long-running production. Why does it forget a core constraint after a week? Why does it re-introduce itself every morning? Why does it pick the wrong tool even though it was corrected three days ago?
At Sistava, where you can hire autonomous AI employees, we had to solve this problem to survive. We run a workforce of around 1,000 AI employees in production, operating continuously across live environments for over two months. At this scale, standard context strategies fail. These systems don’t get a polite session reset; they face a massive real-world hurdle: facts change over time.
If a user utilizes Gmail today and switches to Outlook next month, an agent needs to track both. It has to know which one is current, exactly when the switch happened, and it cannot act like the old truth is still valid. Standard vector database similarity scores do not understand chronological decay or truth overrides. Mix old and new context, and the agent confidently fabricates or forgets the one detail that mattered.
After extensive runtime experience scaling this workforce, the obvious answer - pick a vector store, dump text chunks in, and hope for the best - completely broke. Memory in a long-running agent isn’t a single database. It requires at least seven distinct layers running in parallel across multiple database types.

The Architectural Split (The CoALA Framework)
The academic literature has already recognized these limitations. The seminal CoALA paper (Princeton, 2023) formalized the episodic, semantic, and procedural split from cognitive science for language model agents. It outlines modular components: working memory as a short-term scratchpad, plus long-term episodic for experiences, semantic for facts, and procedural for skills.
In a production environment, each of these layers requires its own write rules, its own lifecycle, and its own read path. They cannot run as a loose stack; they must be isolated so they do not contaminate one another.

  1. Working Memory
    This is the active, per-turn scratchpad holding the immediate plan-so-far, the raw tool output that just came back, or transient chain-of-thought reasoning. It lives entirely within the LLM’s native context window or as an in-memory variable in the runtime environment.
    The Production Lesson: Do not let working memory leak. Transient scratchwork must never accidentally flush into long-term storage, or the agent will begin writing unverified thoughts into its historical knowledge base. Enforce a hard wall - working memory has no persistent backing store. It lives, it dies, it is gone.

  2. Conversation Memory
    This tracks the immediate message history so the agent doesn’t have to re-derive the active thread context on every turn. Most modern agent frameworks ship a checkpointer that auto-loads thread history from a Postgres backend on invocation.
    The Production Lesson: Run a summarizer middleware that triggers when the live conversation crosses a strict token threshold. It compresses older turns into a single structural system message while keeping the recent tail intact, maintaining a dense, cost-efficient context window.

  3. Episodic Memory
    A time-indexed log of past execution loops, historical runs, and specifically, the failures (“Last Tuesday the webhook timed out, so I routed through the fallback queue”). It provides chronological continuity.
    The Production Lesson: A vector store alone fails here because similarity scoring doesn’t understand time. Store raw transcripts alongside LLM-generated execution summaries, keyed explicitly by thread_id and timestamp. Use a background cron job to truncate older episodes to summaries only, rather than forcing the agent to handle eviction at runtime.

sistava.com memory inspection4. Semantic Memory
This stores slow-changing, deterministic facts about the user, the business, or integrated tools (“The core platform is called Atlas”, “The manager prefers brief markdown reports”). It is edited in place, never blindly appended.
The Production Lesson: Split this layer into two distinct substrates: a human-editable markdown file (the “Sovereign Notebook”) and an LLM-extracted graph. If they disagree, the notebook explicitly wins. This gives operators a clear vector to intervene; if an extracted fact is noisy, a manual entry in the notebook out-votes the graph noise on equal footing.

  1. Knowledge Graph
    While semantic memory holds raw facts, the knowledge graph maps the structural edges between entities - who did what, which event caused what, or which entity is a duplicate of another.
    A vector store treats text chunks like isolated islands; a graph database (such as Neo4j, Memgraph, or KuzuDB) connects them. It allows an agent to walk contextually from a specific customer entity straight to the exact email thread where a pricing tier was modified without re-reading thousands of irrelevant chunks.
    AI Employee knowledge graph at sistava.com

Handling Changing Realities: Temporal Edges
The non-obvious requirement of the graph layer is temporal awareness. To handle shifting user preferences or infrastructure changes over months of runtime, you must stop deleting or overwriting data when state changes.
Instead, every extracted fact in the semantic and graph layers needs a valid_at and invalid_at timestamp:
(User) -[USES_TOOL {valid_at: “2024-01-01”, invalid_at: “2026-02-15”}]-> (Gmail)
(User) -[USES_TOOL {valid_at: “2026-02-16”, invalid_at: null}]–> (Outlook)
When today’s session contradicts yesterday’s state, the ingestion pipeline invalidates the old edge instead of erasing it. This preserves a clean, immutable audit trail, allowing the LLM to logically reason about when a preference shifted or an infrastructure stack was updated.
The Build vs. Buy Lesson: Do not write this temporal logic yourself. Utilize open-source libraries that sit on top of your graph DB to handle the LLM-driven extraction, deduplication, and contradiction detection. Writing relationship-inference engines from scratch can easily burn six months of development time.

  1. Procedural Memory
    Procedural memory stores execution mechanics and behavioral habits, not world facts. It dictates how an agent performs tasks (“When checking a raw CSV dataset, first validate header consistency”).
    This data lives in structured skill files (typically markdown documents) that the agent loads on demand based on task routing. Some are explicitly authored by engineers; others are written by the agent itself during asynchronous self-reflection steps.
    The Production Lesson: Keep semantic and procedural data separated. A fact like “The client uses Slack” is semantic and belongs in the notebook. A rule like “When notifying via a webhook, format payload fields as snake_case” is procedural and belongs in a skill file.

  2. Checkpoints
    Operating underneath all other layers is a highly serializable, low-latency snapshot of the exact execution state of an agent workflow. This is not thread history; it is the active node in the graph, the pending tool payloads, and the unwritten output stream.
    It is the difference between a background container crashing and losing a forty-minute execution loop, or surviving a pod restart and picking up cleanly at minute thirty-three. Utilizing a durable execution engine like Temporal gives you deterministic checkpointing at every activity boundary out of the box.

Infrastructure Matrix & Preventing Contamination
To maintain performance, these layers require separate storage shapes, read patterns, and write triggers:
LayerStorage ShapeWrite TriggerRead PatternWorkingIn-memory scratchpadPer-turn executionNative context window injectionConversationAppend-only log + summarizerEvery incoming messageAuto-loaded on invocationEpisodicTime-indexed transcript + JSON summariesPost-message background workerRecency-weighted semantic retrievalSemantic (Notebook)Single editable Markdown fileExplicit agent tool writesFull text injected to promptSemantic (Facts)Graph DB (Neo4j class)Auto-extracted post-messageEntity-anchored sub-graph matchingKnowledge GraphGraph DB with temporal propertiesUnified extraction loop with factsContextual edge-walking between nodesProceduralMarkdown skill filesHuman authorship or reflectionDynamically loaded based on taskCheckpointsKV Store / Postgres / Workflow engineEvery single execution stepInstantly restored on worker restart
Preventing Contamination
Naming the layers is straightforward; wiring them without cross-contamination is where production pipelines fail.
Episodic leaking into Semantic: If every line of a historical brainstorming session gets extracted as a hard “fact,” the agent will interpret a transient hypothetical idea as absolute truth. Enforce strict LLM confidence thresholds or run your fact extraction pipelines on summarized episodes rather than raw chat logs.
Conversation leaking into the Graph: Active conversation is full of throwaway syntax and short pleasantries. Ingesting every message verbatim fills a graph database with garbage nodes. Enforce length-gated ingestion filters to skip processing short, transactional messages.

Managing Upstream LLM Costs
An advanced knowledge graph ingestion pipeline requires between five to nine discrete LLM calls per message (handling entity extraction, graph deduplication, relationship inference, contradiction testing, and entity summary updates), alongside multiple embedding calls. Multiplied across thousands of active conversations running concurrently, background memory costs can quickly eclipse primary agent execution costs.
To keep this sustainable at scale, bake in kill switches and per-tenant gates from day one. Every layer running unattended in the background must have a configuration-level flag or a feature toggle. When an upstream model update or unexpected schema change causes an extraction loop to degrade or spin out of control, you need a way to stop the financial bleeding instantly without triggering an emergency production redeployment.
The Rebuild Blueprint
If you are starting over building an agent memory infrastructure today, this is the recommended development order:
Map the Concerns First: Do not select an orchestration framework based on hype. Map how your system will handle these seven distinct concerns before writing application logic.
Postgres for Foundations: Use Postgres for conversation history and step-level checkpointing. Boring, ACID-compliant storage is exactly what you want here.
Path-Routed KV for Filesystems: Implement a simple key-value store for notebooks and skill files, allowing the agent to interact with its procedural knowledge using clean, standard filesystem tool calls.
Native Graph + Temporal Constraints: Deploy a native graph database (Neo4j, Memgraph, or KuzuDB) paired with an off-the-shelf library that manages temporal constraints natively.
Tight Vector Tooling: Use a highly optimized vector store (pgvector, Qdrant, or Weaviate) specifically to index static external knowledge documents like Notion workspaces, Slack history, or uploaded manuals.

Ultimately, separating transient reasoning from immutable history and structured relational facts is what transforms a fragile chatbot into a reliable system. By treating memory as a multi-layered infrastructure concern, you build an environment where an agent’s capability doesn’t degrade over time , it compounds.
For more details continue reading at https://sistava.com/en/insights/ai-agent-memory.
sistava.com knowledge ingestionBuilding Agent Memory Yourself?
The seven layers, the wiring, and the cost ceilings are a lot to get right on the first run.
If you want this exact architecture adapted to your tech stack, check out our support options at Sista AI. If you would rather talk engineer-to-engineer, I take a few of these architectural deep dives personally. You can reach me directly at zalt.me.

sistava knowledge base