<?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>Forem: Nour Mohamed Amine</title>
    <description>The latest articles on Forem by Nour Mohamed Amine (@zeflq).</description>
    <link>https://forem.com/zeflq</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F171789%2F0f8d57bc-625f-42c4-b823-5b8dd8c30c85.png</url>
      <title>Forem: Nour Mohamed Amine</title>
      <link>https://forem.com/zeflq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/zeflq"/>
    <language>en</language>
    <item>
      <title>pi-reviewer Part 2: A Local Review UI That Puts You in Control</title>
      <dc:creator>Nour Mohamed Amine</dc:creator>
      <pubDate>Tue, 17 Mar 2026 23:20:20 +0000</pubDate>
      <link>https://forem.com/zeflq/pi-reviewer-part-2-a-local-review-ui-that-puts-you-in-control-4lmc</link>
      <guid>https://forem.com/zeflq/pi-reviewer-part-2-a-local-review-ui-that-puts-you-in-control-4lmc</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/zeflq/why-ai-code-review-fails-without-project-context-4f60"&gt;Part 1&lt;/a&gt; I talked about why AI code review falls flat without project context, and how pi-reviewer fixes that by feeding your conventions to the agent before it reads a single line of diff.&lt;/p&gt;

&lt;p&gt;This part is about what happens after the review runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with "just post a comment"
&lt;/h2&gt;

&lt;p&gt;Most AI review tools finish the job by dumping everything into a GitHub PR comment. You end up with a wall of findings, some useful, some not, and no real way to act on them beyond reading through and manually deciding what to do with each one.&lt;/p&gt;

&lt;p&gt;pi-reviewer works differently. After the agent finishes, a browser UI opens where you go through every finding and decide what to do with it before anything gets sent anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;--ui&lt;/code&gt; flag
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/review --ui
/review --ssh --ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the review is done, a local server starts and your browser opens automatically. No extra setup, no cloud, nothing to configure. The server shuts down as soon as you take an action or close the tab.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you are looking at
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Sidebar&lt;/strong&gt; is a GitHub-style file tree on the left. Files are grouped by folder, you can collapse and expand folders, and each one shows a comment count badge that adds up from its children. Click a file and the diff jumps to it with a blue border so you always know where you are. Click anywhere else and it deselects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Syntax highlighting&lt;/strong&gt; colorizes the diff by language. TypeScript, Python, Go, Rust, Java and more are all supported, using the same token colors as GitHub. The red and green diff backgrounds stay intact, the syntax colors just sit on top.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Split and unified toggle&lt;/strong&gt; lets you switch between side-by-side and single-column views whenever you want. It applies to all files at once.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going through the findings
&lt;/h2&gt;

&lt;p&gt;Every comment needs a decision before you can do anything. You have three options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Accept&lt;/strong&gt; - include this finding when sending back to the agent&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Reject&lt;/strong&gt; - skip it, do not send it&lt;/li&gt;
&lt;li&gt;💬 &lt;strong&gt;Discuss&lt;/strong&gt; - accept it and add your own note that gets sent alongside it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The header shows how many you have decided so far. Save, Send, and Save &amp;amp; Send stay greyed out until everything has a decision. No accidental sends.&lt;/p&gt;

&lt;p&gt;As you go through them the cards update visually. Accepted ones get a green tint, rejected ones fade. There is a jump button that skips straight to the next undecided comment so you do not have to scroll around.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you can do at the end
&lt;/h2&gt;

&lt;p&gt;Once every comment has a decision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Save&lt;/strong&gt; writes the full review and your decisions to &lt;code&gt;pi-review.md&lt;/code&gt;, no agent call&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send&lt;/strong&gt; injects the accepted and discussed findings into the agent as a follow-up turn&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save &amp;amp; Send&lt;/strong&gt; does both&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Send and Save &amp;amp; Send only activate if you accepted or discussed at least one finding. There is no point starting an agent turn with nothing to say.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSH mode
&lt;/h2&gt;

&lt;p&gt;Working on a remote machine? Just add &lt;code&gt;--ssh&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;/review &lt;span class="nt"&gt;--ssh&lt;/span&gt; &lt;span class="nt"&gt;--ui&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent fetches the diff over SSH, runs the review remotely, and sends the result back. The UI opens locally with the full diff and findings. No second SSH trip needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Theme
&lt;/h2&gt;

&lt;p&gt;The dark and light toggle remembers your choice across reviews using &lt;code&gt;~/.pi/pi-reviewer/config.json&lt;/code&gt;. Since the local server picks a random port every time, browser storage would reset on every review, so the preference lives server-side instead.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pi &lt;span class="nb"&gt;install &lt;/span&gt;https://github.com/zeflq/pi-reviewer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then inside the pi TUI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/review &lt;span class="nt"&gt;--ui&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drop an &lt;code&gt;AGENTS.md&lt;/code&gt; or &lt;code&gt;CLAUDE.md&lt;/code&gt; at your project root to give the agent context about your conventions. Add a &lt;code&gt;REVIEW.md&lt;/code&gt; if you want to be specific about what to flag and what to skip.&lt;/p&gt;

&lt;p&gt;The full roadmap is in &lt;a href="https://github.com/zeflq/pi-reviewer/blob/main/TODO.md" rel="noopener noreferrer"&gt;TODO.md&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;pi-reviewer is open source at &lt;a href="https://github.com/zeflq/pi-reviewer" rel="noopener noreferrer"&gt;github.com/zeflq/pi-reviewer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>codereview</category>
    </item>
    <item>
      <title>Why AI Code Review Fails Without Project Context</title>
      <dc:creator>Nour Mohamed Amine</dc:creator>
      <pubDate>Wed, 11 Mar 2026 04:57:06 +0000</pubDate>
      <link>https://forem.com/zeflq/why-ai-code-review-fails-without-project-context-4f60</link>
      <guid>https://forem.com/zeflq/why-ai-code-review-fails-without-project-context-4f60</guid>
      <description>&lt;p&gt;Every AI code review starts the same way.&lt;/p&gt;

&lt;p&gt;The bot opens your PR. It scans the diff. It flags a missing &lt;code&gt;try/catch&lt;/code&gt;, suggests a more descriptive variable name, and notes that you could memoize that function for performance.&lt;/p&gt;

&lt;p&gt;All technically correct. None of it useful.&lt;/p&gt;

&lt;p&gt;Because it doesn't know that &lt;code&gt;fetchUser&lt;/code&gt; is an intentional naming convention your team enforces. That error handling is delegated to a global boundary. That performance isn't the concern here — correctness is. The bot doesn't know your project. It never did.&lt;/p&gt;

&lt;p&gt;This isn't a model problem. It's a &lt;strong&gt;context problem&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: context-aware review
&lt;/h2&gt;

&lt;p&gt;That's what &lt;code&gt;pi-reviewer&lt;/code&gt; is built around — a GitHub Action and &lt;a href="https://github.com/mariozechner/pi" rel="noopener noreferrer"&gt;pi&lt;/a&gt; TUI extension that brings your project conventions into every review.&lt;/p&gt;

&lt;p&gt;Before the agent sees a single line of diff, it reads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;AGENTS.md&lt;/code&gt; or &lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/strong&gt; — your general project conventions: naming rules, architecture decisions, patterns to follow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;REVIEW.md&lt;/code&gt;&lt;/strong&gt; — review-specific rules: what to always flag, what to explicitly skip&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Markdown links in those files are followed recursively. If your &lt;code&gt;AGENTS.md&lt;/code&gt; links to &lt;code&gt;docs/api-conventions.md&lt;/code&gt;, that file gets inlined too. The agent sees the full picture, not just the summary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Review Guidelines&lt;/span&gt;

&lt;span class="gu"&gt;## Always flag&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`fetch`&lt;/span&gt; calls missing &lt;span class="sb"&gt;`res.ok`&lt;/span&gt; check before &lt;span class="sb"&gt;`.json()`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; API endpoints not versioned under &lt;span class="sb"&gt;`/api/v1/`&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Functions named &lt;span class="sb"&gt;`getData`&lt;/span&gt;, &lt;span class="sb"&gt;`doStuff`&lt;/span&gt;, or other generic names

&lt;span class="gu"&gt;## Skip&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Formatting-only changes
&lt;span class="p"&gt;-&lt;/span&gt; Changes inside &lt;span class="sb"&gt;`pi-review.md`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a &lt;code&gt;REVIEW.md&lt;/code&gt;. The agent now knows what &lt;em&gt;your team&lt;/em&gt; cares about — not what a generic model thinks good code looks like.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a context-aware review looks like
&lt;/h2&gt;

&lt;p&gt;Here's what changed after adding project context.&lt;/p&gt;

&lt;p&gt;Before: the agent flagged a missing type annotation on an internal helper. Suggested renaming a variable. Noted a &lt;code&gt;console.log&lt;/code&gt; left in.&lt;/p&gt;

&lt;p&gt;After: it caught an unversioned API endpoint added in the same PR. Flagged a &lt;code&gt;fetch&lt;/code&gt; call missing the &lt;code&gt;res.ok&lt;/code&gt; check — exactly the rule in &lt;code&gt;REVIEW.md&lt;/code&gt;. Skipped the formatting-only change in the generated file, as instructed.&lt;/p&gt;

&lt;p&gt;Same model. Same diff. Completely different review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Severity you control
&lt;/h2&gt;

&lt;p&gt;Not every finding deserves equal weight. &lt;code&gt;pi-reviewer&lt;/code&gt; lets you filter by severity — so you can focus on what matters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;zeflq/pi-reviewer@main&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;github-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
    &lt;span class="na"&gt;pi-api-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.PI_API_KEY }}&lt;/span&gt;
    &lt;span class="na"&gt;min-severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;warn&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set &lt;code&gt;min-severity: warn&lt;/code&gt; and the agent skips INFO-level suggestions entirely — both in what it generates and in what gets posted to the PR. You can also trigger a manual review from the GitHub Actions UI and choose the severity level on the fly.&lt;/p&gt;

&lt;p&gt;Three tiers: 🔴 CRITICAL for bugs and security issues, 🟡 WARN for logic and type errors, 🔵 INFO for style and suggestions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model-agnostic, built on pi mono
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pi-reviewer&lt;/code&gt; runs on &lt;a href="https://github.com/mariozechner/pi" rel="noopener noreferrer"&gt;pi&lt;/a&gt; — a terminal-based coding agent that sits on top of the pi mono platform. One &lt;code&gt;PI_API_KEY&lt;/code&gt; works across all supported models and providers. You pick the model, pi routes the request.&lt;/p&gt;

&lt;p&gt;That means you're not locked into a single provider. Swap models without touching your workflow. The review logic stays the same.&lt;/p&gt;

&lt;p&gt;It also works over SSH. If your project lives on a remote machine, &lt;code&gt;--ssh&lt;/code&gt; mode lets the agent fetch the diff and read your conventions directly on the remote — no local copy needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it compares to Claude Code PR Review
&lt;/h2&gt;

&lt;p&gt;Anthropic recently shipped &lt;a href="https://code.claude.com/docs/en/code-review" rel="noopener noreferrer"&gt;Code Review&lt;/a&gt; — a managed PR review service built into Claude Code. It reads &lt;code&gt;CLAUDE.md&lt;/code&gt; and &lt;code&gt;REVIEW.md&lt;/code&gt;, runs multiple specialized agents against your full codebase in parallel, and posts inline findings with severity tags. It's genuinely impressive.&lt;/p&gt;

&lt;p&gt;But it comes with constraints that may not fit every team.&lt;/p&gt;

&lt;p&gt;It's a &lt;strong&gt;managed service&lt;/strong&gt; — runs on Anthropic's infrastructure, requires a GitHub App installation, available on Teams and Enterprise plans only. Reviews average $15–25 each. It's Claude-only, and you don't control where it runs.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pi-reviewer&lt;/code&gt; runs in your own CI, costs what your token usage costs, works with any model through pi mono, and needs nothing more than a secret and a workflow file. No GitHub App. No admin approval flow.&lt;/p&gt;

&lt;p&gt;And if you want to review locally before you push — without opening a PR at all — the pi TUI extension gives you &lt;code&gt;/review&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;p&gt;Both tools read your &lt;code&gt;CLAUDE.md&lt;/code&gt; and &lt;code&gt;REVIEW.md&lt;/code&gt;. The difference is where they run, what they cost, and how much control you keep.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set it up once, forget about it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx github:zeflq/pi-reviewer init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That generates a workflow file. Add your &lt;code&gt;PI_API_KEY&lt;/code&gt; secret. Every PR from that point on gets a review that knows your project.&lt;/p&gt;

&lt;p&gt;The context files — &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;REVIEW.md&lt;/code&gt; — live in your repo. Version-controlled, team-editable, evolve with the project. The better you document your conventions, the better the reviews get.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shift
&lt;/h2&gt;

&lt;p&gt;The insight isn't that AI can review code. It's that AI review without project context is just another linter with better prose.&lt;/p&gt;

&lt;p&gt;The review that matters is the one that knows &lt;em&gt;why&lt;/em&gt; your codebase looks the way it does — and checks the diff against that, not against some generic idea of good software.&lt;/p&gt;

&lt;p&gt;That's the layer that's been missing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zeflq/pi-reviewer" rel="noopener noreferrer"&gt;github.com/zeflq/pi-reviewer&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Context is everything. Diff without it is just noise.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>development</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The Missing Layer: Why Your Coding Agent Needs to Know Your Decisions</title>
      <dc:creator>Nour Mohamed Amine</dc:creator>
      <pubDate>Sun, 01 Mar 2026 15:49:29 +0000</pubDate>
      <link>https://forem.com/zeflq/the-missing-layer-why-your-coding-agent-needs-to-know-your-decisions-2g99</link>
      <guid>https://forem.com/zeflq/the-missing-layer-why-your-coding-agent-needs-to-know-your-decisions-2g99</guid>
      <description>&lt;p&gt;Every session with a coding agent starts the same way.&lt;/p&gt;

&lt;p&gt;You open a new conversation, and before you can get anything done, you spend 10-20 minutes re-explaining the project. Clean architecture. No Prisma imports in use cases. Domain layer here, infrastructure there. We use this pattern for repositories. Oh, and we decided last week to enforce 85% test coverage on all use cases.&lt;/p&gt;

&lt;p&gt;The agent nods along — then next session, you do it again.&lt;/p&gt;

&lt;p&gt;This isn't a model problem. Claude, GPT, whatever — they're all capable. The problem is &lt;strong&gt;context&lt;/strong&gt;. Specifically, the decisions your team has already made. The agent doesn't know them unless you tell it. Every. Single. Time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Decisions are the missing layer
&lt;/h2&gt;

&lt;p&gt;When a senior dev joins a project, they don't just read the code. They absorb the &lt;em&gt;why&lt;/em&gt; behind it — the constraints, the trade-offs, the rules the team agreed on. That's what makes them productive fast.&lt;/p&gt;

&lt;p&gt;A coding agent only gets the code. The decisions live in someone's head, in a Slack thread from 3 months ago, or in a doc nobody reads.&lt;/p&gt;

&lt;p&gt;That's the gap &lt;code&gt;pi-project-memory&lt;/code&gt; fills.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pi-project-memory&lt;/code&gt; is an extension for &lt;a href="https://github.com/mariozechner/pi" rel="noopener noreferrer"&gt;pi&lt;/a&gt;, a terminal-based coding agent. It gives the agent a persistent, project-local memory — stored as plain markdown files in &lt;code&gt;.pi/project-memory/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When you make a decision — architecture, tooling, conventions — the extension captures it. Either automatically from your prompt, or with a quick &lt;code&gt;/memory remember&lt;/code&gt;. It classifies it: decision, pattern, preference, or gotcha. Next session, it's injected into context before the agent starts. No re-explaining.&lt;/p&gt;

&lt;p&gt;Four files. No database. No cloud sync. Just markdown you can read, edit, and commit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.pi/project-memory/
├── MEMORY.md        ← injected every session
├── decisions.md
├── patterns.md
├── preferences.md
└── gotchas.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The moment it clicked
&lt;/h2&gt;

&lt;p&gt;A teammate started using pi on our project for the first time. A few minutes in, they messaged: &lt;em&gt;"how does the agent know all this stuff about our architecture?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It had read the memory files.&lt;/p&gt;

&lt;p&gt;We hadn't written an onboarding doc. We hadn't sent them a Notion page or a Slack thread. The agent just... knew — because decisions made across dozens of sessions had been captured as they happened.&lt;/p&gt;

&lt;p&gt;That's the shift that surprised us most: &lt;strong&gt;the agent became a participant in the project, not just a tool&lt;/strong&gt;. It doesn't only read from the memory files. It writes to them. When it encounters a decision worth keeping, it proposes saving it. Over time, it builds up a shared understanding of the project alongside the team.&lt;/p&gt;




&lt;h2&gt;
  
  
  Auto-capture, not manual bookkeeping
&lt;/h2&gt;

&lt;p&gt;The extension works in the background. When you type something that looks like a decision — &lt;em&gt;"we will use clean architecture"&lt;/em&gt;, &lt;em&gt;"never import Prisma directly in use cases"&lt;/em&gt;, &lt;em&gt;"all use cases must be tested, 85% coverage"&lt;/em&gt; — it classifies it and asks if you want to save it.&lt;/p&gt;

&lt;p&gt;High-confidence captures save silently. Mid-confidence ones surface a quick confirmation. You stay in flow.&lt;/p&gt;

&lt;p&gt;It also learns from what the agent discovers. Ask it to scan your feature folder structure? If the response contains a structured template, the extension proposes saving that too — so future features follow the same blueprint.&lt;/p&gt;




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

&lt;p&gt;The extension is open source and early. The next big piece is &lt;code&gt;/memory export&lt;/code&gt; — syncing your captured decisions to &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;.cursor/rules&lt;/code&gt;, or &lt;code&gt;AGENTS.md&lt;/code&gt;, so the memory travels beyond pi sessions and becomes part of the project for every tool and every teammate.&lt;/p&gt;

&lt;p&gt;If you're building with pi and tired of re-explaining your architecture every session — try it. And if you want to contribute, the repo is open.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/zeflq/pi-project-memory" rel="noopener noreferrer"&gt;github.com/zeflq/pi-project-memory&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built while building. Decisions captured along the way.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>development</category>
      <category>agents</category>
    </item>
    <item>
      <title>Stop Fighting Context Limits: How Multi-Agent Systems Solved My Development Chaos(Part 1)</title>
      <dc:creator>Nour Mohamed Amine</dc:creator>
      <pubDate>Sun, 28 Dec 2025 01:28:26 +0000</pubDate>
      <link>https://forem.com/zeflq/stop-fighting-context-limits-how-multi-agent-systems-solved-my-development-chaospart-1-2a4a</link>
      <guid>https://forem.com/zeflq/stop-fighting-context-limits-how-multi-agent-systems-solved-my-development-chaospart-1-2a4a</guid>
      <description>&lt;p&gt;&lt;strong&gt;Part 1 of 3&lt;/strong&gt; | Reading Time: 10 minutes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Single AI agents struggle with context overload and inconsistent quality. Multi-agent systems solve this by splitting work across specialized agents with clear boundaries and explicit handoff contracts. This post explains why and introduces the architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem with Single-Agent Development
&lt;/h2&gt;

&lt;p&gt;I've watched countless development teams hit the same wall with AI-assisted development. They start excited, using Claude or GPT to build features. Then reality sets in.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Single-Agent Bottleneck
&lt;/h3&gt;

&lt;p&gt;When using a single AI agent for development:&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Context overload&lt;/strong&gt;: The agent tries to handle UX + frontend + backend + database all at once&lt;br&gt;
❌ &lt;strong&gt;Inconsistent quality&lt;/strong&gt;: No specialization leads to generic, one-size-fits-all solutions&lt;br&gt;
❌ &lt;strong&gt;Poor integration&lt;/strong&gt;: No clear handoff points between layers&lt;br&gt;
❌ &lt;strong&gt;Architectural drift&lt;/strong&gt;: No governance over structural decisions&lt;br&gt;
❌ &lt;strong&gt;Knowledge dilution&lt;/strong&gt;: Expert-level code in one area, beginner-level in another&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real example&lt;/strong&gt;: Ask a single agent to "build a user profile page" and you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generic React components (not following your design system)&lt;/li&gt;
&lt;li&gt;API endpoints that don't match your backend patterns&lt;/li&gt;
&lt;li&gt;Database queries that bypass your repository layer&lt;/li&gt;
&lt;li&gt;Security checks that are inconsistent with your auth strategy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent isn't bad—it's just doing too much.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Multi-Agent Solution
&lt;/h2&gt;

&lt;p&gt;What if instead of one generalist, you had a team of specialists?&lt;/p&gt;
&lt;h3&gt;
  
  
  The Core Insight
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Good software teams have specialists&lt;/strong&gt;. You don't ask your UX designer to write database migrations. You don't ask your backend engineer to design user flows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-agent systems apply the same principle to AI development&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  What You Get
&lt;/h3&gt;

&lt;p&gt;A well-designed multi-agent system provides:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Clear separation of concerns&lt;/strong&gt;: Each agent is a domain expert&lt;br&gt;
✅ &lt;strong&gt;Consistent quality&lt;/strong&gt;: Specialists produce better work than generalists&lt;br&gt;
✅ &lt;strong&gt;Explicit contracts&lt;/strong&gt;: Handoffs force clarity at boundaries&lt;br&gt;
✅ &lt;strong&gt;Architectural governance&lt;/strong&gt;: A coordinating agent enforces coherence&lt;br&gt;
✅ &lt;strong&gt;Scalable complexity&lt;/strong&gt;: Add agents as your needs grow&lt;/p&gt;


&lt;h2&gt;
  
  
  The Three-Layer Architecture
&lt;/h2&gt;

&lt;p&gt;Here's the complete model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────┐
│  Layer 1: Orchestration (brain-agent)               │
│  • Slices work into small chunks                    │
│  • Routes to appropriate specialists                │
│  • Enforces architectural decisions (ADRs)          │
│  • Validates integration between agents             │
└─────────────────────────────────────────────────────┘
                        ↓
┌─────────────────────────────────────────────────────┐
│  Layer 2: Specialist Agents                         │
│  • ux-agent: User experience &amp;amp; interaction flows    │
│  • react-agent: UI components &amp;amp; client state        │
│  • next-agent: Routing &amp;amp; server/client boundaries   │
│  • backend-agent: APIs, validation &amp;amp; persistence    │
│  • [Your custom agents as needed...]                │
└─────────────────────────────────────────────────────┘
                        ↓
┌─────────────────────────────────────────────────────┐
│  Layer 3: Shared Foundation                         │
│  • conventions.md: Generic dev principles (KISS)    │
│  • project-rules/: YOUR architecture patterns       │
│  • ADR registry: Documented decisions               │
└─────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 1: The Brain Agent (Orchestrator)
&lt;/h3&gt;

&lt;p&gt;Think of this as your tech lead. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Takes user requests and breaks them into small, shippable slices (1-2 hours each)&lt;/li&gt;
&lt;li&gt;Routes each slice to the right specialist&lt;/li&gt;
&lt;li&gt;Enforces architectural decisions through ADRs (Architecture Decision Records)&lt;/li&gt;
&lt;li&gt;Ensures all the pieces integrate properly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example workflow&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User: "Build a user profile page"

brain-agent:
  SLC-001 → ux-agent: Design profile layout and states
  SLC-002 → react-agent: Build ProfilePage component
  SLC-003 → backend-agent: Create GET /api/users/:id endpoint
  SLC-004 → next-agent: Wire route and data fetching
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 2: Specialist Agents
&lt;/h3&gt;

&lt;p&gt;Each specialist owns a specific domain:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ux-agent&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Owns: User flows, wireframes, interaction patterns, accessibility&lt;/li&gt;
&lt;li&gt;Delivers: UI specs with states, variants, and acceptance criteria&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;react-agent&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Owns: React components, hooks, UI state management, forms&lt;/li&gt;
&lt;li&gt;Delivers: Clean, warning-free React code following modern patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;next-agent&lt;/strong&gt; (or framework-specific agent)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Owns: Routing, layouts, server/client boundaries, metadata&lt;/li&gt;
&lt;li&gt;Delivers: Route scaffolding and integration wiring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;backend-agent&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Owns: API design, DTOs, persistence, validation, auth boundaries&lt;/li&gt;
&lt;li&gt;Delivers: Endpoints, database changes, error handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You can add more&lt;/strong&gt;: testing-agent, deployment-agent, data-agent, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 3: Shared Foundation
&lt;/h3&gt;

&lt;p&gt;This is where consistency lives:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;conventions.md&lt;/strong&gt; - Generic principles that work anywhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KISS (Keep It Simple)&lt;/li&gt;
&lt;li&gt;SOLID principles&lt;/li&gt;
&lt;li&gt;YAGNI (You Aren't Gonna Need It)&lt;/li&gt;
&lt;li&gt;Small, incremental work&lt;/li&gt;
&lt;li&gt;Explicit contracts over assumptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;project-rules/&lt;/strong&gt; - YOUR specific patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;01-architecture.md&lt;/code&gt;: Your chosen architecture (feature-first? clean architecture?)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;02-tech-stack.md&lt;/code&gt;: Your frameworks, libraries, naming conventions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;03-security.md&lt;/code&gt;: Your auth strategy, multi-tenancy rules&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ADR registry&lt;/strong&gt; - Documented decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why did we choose this pattern?&lt;/li&gt;
&lt;li&gt;What alternatives did we consider?&lt;/li&gt;
&lt;li&gt;What are the trade-offs?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key Principles
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Feature Slicing, Not Layer Slicing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Bad&lt;/strong&gt; (layer slicing):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Week 1: Build all database models
Week 2: Build all API endpoints
Week 3: Build all UI components
Week 4: Integration (surprise! nothing works together)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Good&lt;/strong&gt; (feature slicing):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SLC-001 (2 hours): Complete user login
  - Model + API + UI + Integration = ✅ Working feature

SLC-002 (2 hours): Complete profile view
  - Model + API + UI + Integration = ✅ Working feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each slice is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;XS&lt;/strong&gt;: 1-2 hours (single component/endpoint)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S&lt;/strong&gt;: 0.5-1 day (full feature with integration)&lt;/li&gt;
&lt;li&gt;Fully integrated or explicitly marked as incomplete&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Explicit Contracts Over Implicit Assumptions
&lt;/h3&gt;

&lt;p&gt;Every handoff between agents has a contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;### HANDOFF&lt;/span&gt;
From: backend-agent
To: react-agent
Slice-ID: SLC-042

Public contract:
&lt;span class="p"&gt;-&lt;/span&gt; Endpoint: POST /api/users
&lt;span class="p"&gt;-&lt;/span&gt; Request: { name: string, email: string }
&lt;span class="p"&gt;-&lt;/span&gt; Response: { id: string, name: string, email: string }
&lt;span class="p"&gt;-&lt;/span&gt; Errors: 400 (validation), 409 (duplicate), 500 (server)

Edge cases handled:
&lt;span class="p"&gt;-&lt;/span&gt; Duplicate email → 409 with message
&lt;span class="p"&gt;-&lt;/span&gt; Invalid email format → 400 with field errors
&lt;span class="p"&gt;-&lt;/span&gt; Missing required field → 400 with field errors

How to test:
&lt;span class="p"&gt;1.&lt;/span&gt; POST valid data → expect 201
&lt;span class="p"&gt;2.&lt;/span&gt; POST duplicate email → expect 409
&lt;span class="p"&gt;3.&lt;/span&gt; POST invalid email → expect 400
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No assumptions. No "I think it returns...". Crystal clear.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Governance Without Bureaucracy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;: Too much governance = bureaucracy, too little = chaos&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution&lt;/strong&gt;: ADRs (Architecture Decision Records) only for structural decisions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Requires ADR&lt;/strong&gt; (blocks work until approved):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changes affecting &amp;gt;2 features&lt;/li&gt;
&lt;li&gt;New architectural patterns&lt;/li&gt;
&lt;li&gt;Changes to shared contracts&lt;/li&gt;
&lt;li&gt;Security implications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;No ADR needed&lt;/strong&gt; (agent proceeds):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local implementation details&lt;/li&gt;
&lt;li&gt;Single-feature changes&lt;/li&gt;
&lt;li&gt;Following existing patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps you moving fast while preventing architectural disasters.&lt;/p&gt;




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

&lt;h3&gt;
  
  
  Real-World Comparison
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt; (single agent):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Me: "Add user authentication"

Agent:
  *Generates generic JWT setup*
  *Creates basic auth middleware*
  *Makes questionable security choices*
  *No integration with existing patterns*

Result: 6 hours debugging, 3 hours refactoring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt; (multi-agent):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Me: "Add user authentication"

brain-agent: *Checks for architectural decision needed*
  → "This affects multiple features. Creating ADR for approval."

ADR-003: Authentication Strategy
  - NextAuth.js v5 with session strategy
  - Middleware for route protection
  - Follows existing patterns in rules/03-security.md

User: *Approves*

brain-agent:
  SLC-010 → backend-agent: Set up NextAuth with providers
  SLC-011 → next-agent: Add auth middleware to routes
  SLC-012 → react-agent: Create login/logout UI
  SLC-013 → backend-agent: Add auth to protected endpoints

Result: Each slice takes 1-2 hours, fully integrated, follows patterns
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Benefits
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Quality&lt;/strong&gt;: Each agent is an expert in their domain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt;: All agents follow the same conventions + your project rules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration&lt;/strong&gt;: Explicit handoffs prevent "works on my machine" moments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Add agents as complexity grows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Clear boundaries make code easier to understand&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditability&lt;/strong&gt;: Slice IDs and handoffs create a paper trail&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Is This For You?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  This approach works best when:
&lt;/h3&gt;

&lt;p&gt;✅ You're building a non-trivial application (not just a landing page)&lt;br&gt;
✅ You have architectural patterns you want to enforce&lt;br&gt;
✅ You need consistency across your codebase&lt;br&gt;
✅ Multiple people (or AI agents) are contributing&lt;br&gt;
✅ You want quality that matches your standards&lt;/p&gt;
&lt;h3&gt;
  
  
  This might be overkill if:
&lt;/h3&gt;

&lt;p&gt;❌ You're building a simple prototype&lt;br&gt;
❌ You have no architectural preferences&lt;br&gt;
❌ You're okay with inconsistent patterns&lt;br&gt;
❌ Speed &amp;gt; quality for your use case&lt;/p&gt;


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

&lt;p&gt;In &lt;strong&gt;Part 2&lt;/strong&gt;, I'll show you exactly how to build this system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File structure and organization&lt;/li&gt;
&lt;li&gt;How to write agent specifications&lt;/li&gt;
&lt;li&gt;Creating your brain-agent&lt;/li&gt;
&lt;li&gt;Setting up conventions and project rules&lt;/li&gt;
&lt;li&gt;Real implementation examples&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Coming soon&lt;/strong&gt;: Part 2: Building Your First Multi-Agent System&lt;/p&gt;


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

&lt;p&gt;Want to experiment with this concept?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5-Minute Exercise&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pick a feature in your current project&lt;/li&gt;
&lt;li&gt;Write down which agents would own which parts&lt;/li&gt;
&lt;li&gt;Define the contract between them&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Feature: User profile edit

ux-agent:
  - Profile edit form states (idle, editing, saving, error)

react-agent:
  - ProfileEditForm component with validation

backend-agent:
  - PATCH /api/users/:id endpoint
  - Validation logic

Contract:
  - Request: { name?: string, bio?: string }
  - Response: Updated user object
  - Errors: 400 (validation), 401 (unauthorized), 404 (not found)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how much clearer the boundaries become?&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;About This Series&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 1: Why Multi-Agent Systems (you are here)&lt;/li&gt;
&lt;li&gt;Part 2: Building Your First Multi-Agent System (coming soon)&lt;/li&gt;
&lt;li&gt;Part 3: Production Best Practices &amp;amp; Pitfalls (coming soon)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;GitHub Template&lt;/strong&gt;: [&lt;a href="https://github.com/zeflq/multi-agent-system-framework" rel="noopener noreferrer"&gt;https://github.com/zeflq/multi-agent-system-framework&lt;/a&gt;]&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Questions or thoughts?&lt;/strong&gt; Drop them in the comments. I'd love to hear about your experiences with AI-assisted development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Last Updated&lt;/strong&gt;: 2025-12-28&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>development</category>
      <category>productivity</category>
      <category>ai</category>
    </item>
    <item>
      <title>3 Game Changing Ways React’s New `&lt;Activity&gt;` Component Will Change How You Code</title>
      <dc:creator>Nour Mohamed Amine</dc:creator>
      <pubDate>Sun, 07 Dec 2025 17:10:26 +0000</pubDate>
      <link>https://forem.com/zeflq/3-game-changing-ways-reacts-new-component-will-change-how-you-code-48kh</link>
      <guid>https://forem.com/zeflq/3-game-changing-ways-reacts-new-component-will-change-how-you-code-48kh</guid>
      <description>&lt;p&gt;If you’ve been building React apps for a while, you know the classic pattern by heart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;isVisible&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s simple, it works… and it comes with a really annoying downside: &lt;strong&gt;every time the component hides, its entire state gets wiped out.&lt;/strong&gt;&lt;br&gt;
Counters reset. Inputs lose their text. Cached data disappears.&lt;br&gt;
We’ve all just accepted this as “how React works.”&lt;/p&gt;

&lt;p&gt;Well, not anymore.&lt;/p&gt;

&lt;p&gt;React’s new &lt;code&gt;&amp;lt;Activity&amp;gt;&lt;/code&gt; component finally fixes this pain point but what most developers don’t realize is that preserving state is just the &lt;em&gt;beginning&lt;/em&gt;. &lt;code&gt;&amp;lt;Activity&amp;gt;&lt;/code&gt; quietly unlocks two extremely powerful performance techniques that weren’t possible before.&lt;/p&gt;

&lt;p&gt;Let’s break down the three ways this new primitive is about to reshape the way you think about React starting with the obvious win and ending with two next-level optimizations that will make you look like a performance wizard.&lt;/p&gt;


&lt;h2&gt;
  
  
  1. Stop Losing Component State Every Time You Toggle Visibility
&lt;/h2&gt;

&lt;p&gt;For years, hiding a component meant unmounting it. And unmounting meant losing everything inside it.&lt;/p&gt;

&lt;p&gt;Your form?  ➡️ Blank again.&lt;/p&gt;

&lt;p&gt;Your counter?  ➡️ Back to zero.&lt;/p&gt;

&lt;p&gt;Your fetched data?  ➡️ See you later.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Activity&amp;gt;&lt;/code&gt; changes that. It lets you control visibility &lt;strong&gt;without&lt;/strong&gt; unmounting the component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;Activity&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="s1"&gt;react&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="nf"&gt;MyTogglableComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isVisible&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;mode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;isVisible&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;visible&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;hidden&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Activity&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;&amp;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;When &lt;code&gt;mode="hidden"&lt;/code&gt;, your component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;stays mounted
&lt;/li&gt;
&lt;li&gt;keeps all its internal state
&lt;/li&gt;
&lt;li&gt;keeps user input
&lt;/li&gt;
&lt;li&gt;remembers everything
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here’s the clever part: &lt;strong&gt;side effects pause&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So while your component is “sleeping,” React won’t rerun effects or keep subscriptions active. When you make it visible again, it wakes up exactly where it left off.&lt;/p&gt;

&lt;p&gt;This alone solves a decade old annoyance. But the next two features are where things get &lt;em&gt;really&lt;/em&gt; interesting.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Preload Data &lt;em&gt;Before&lt;/em&gt; Your User Even Asks For It
&lt;/h2&gt;

&lt;p&gt;Think about a modal, a tab, or a panel that fetches data using Suspense. Normally, the fetch only begins when the user opens it. And then… they wait.&lt;/p&gt;

&lt;p&gt;Now imagine wrapping that same component in an &lt;code&gt;&amp;lt;Activity mode="hidden"&amp;gt;&lt;/code&gt; &lt;strong&gt;from the start&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What happens?&lt;/p&gt;

&lt;p&gt;React goes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Okay, let me finish the important stuff first.&lt;br&gt;&lt;br&gt;
Then, when I have some idle time, I’ll go ahead and pre-render this hidden component.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And during that pre-render?&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Your data fetching kicks off early.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By the time the user clicks the button to reveal it, the data is often &lt;em&gt;already loaded&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;No spinner.&lt;br&gt;&lt;br&gt;
No delay.&lt;br&gt;&lt;br&gt;
Just instant UI.&lt;/p&gt;

&lt;p&gt;This is a massive UX upgrade for anything you expect the user will eventually open:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;modals
&lt;/li&gt;
&lt;li&gt;secondary tabs
&lt;/li&gt;
&lt;li&gt;expandable panels
&lt;/li&gt;
&lt;li&gt;sidebar content
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’re basically time traveling your loading state.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Make Your App &lt;em&gt;Feel&lt;/em&gt; Faster With Smarter Hydration
&lt;/h2&gt;

&lt;p&gt;If you’re building with something like Next.js, hydration is a big deal. It’s what makes your server rendered HTML come alive in the browser.&lt;/p&gt;

&lt;p&gt;But hydration has a problem:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;One slow component can block your whole page from becoming interactive.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, a heavy comments section at the bottom of a blog post can delay your entire page even the text at the top that should be usable immediately.&lt;/p&gt;

&lt;p&gt;Wrapping low priority sections in &lt;code&gt;&amp;lt;Activity&amp;gt;&lt;/code&gt; changes the game.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Comments&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even without any props, this tells React:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Hey, treat this as a separate hydration task.&lt;br&gt;&lt;br&gt;
Focus on the important stuff first.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your main UI becomes interactive &lt;em&gt;much&lt;/em&gt; faster
&lt;/li&gt;
&lt;li&gt;Lower priority content hydrates later, during browser idle time
&lt;/li&gt;
&lt;li&gt;Users feel like the page loads instantly, even if a big component is still hydrating in the background
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Profilers show two distinct hydration waves:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;primary content first&lt;/strong&gt;, secondary content later.&lt;/p&gt;

&lt;p&gt;That’s a huge win for perceived performance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts: &lt;code&gt;&amp;lt;Activity&amp;gt;&lt;/code&gt; Is More Than a Component,It’s a New Rendering Primitive
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Activity&amp;gt;&lt;/code&gt; isn’t just a nicer way of hiding components.&lt;br&gt;&lt;br&gt;
It gives you &lt;strong&gt;fine grained control&lt;/strong&gt; over:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;when&lt;/em&gt; components mount
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;when&lt;/em&gt; they hydrate
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;when&lt;/em&gt; they fetch data
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;when&lt;/em&gt; they render
&lt;/li&gt;
&lt;li&gt;and &lt;em&gt;when&lt;/em&gt; they pause side effects
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;State preservation is the obvious benefit but the real power comes from the performance patterns it enables.&lt;/p&gt;

&lt;p&gt;So take a look at your own app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where are you re-fetching data unnecessarily?
&lt;/li&gt;
&lt;li&gt;Where could users benefit from instant modal loads?
&lt;/li&gt;
&lt;li&gt;What heavy components slow down hydration?
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because with a little strategic wrapping, &lt;code&gt;&amp;lt;Activity&amp;gt;&lt;/code&gt; might be the biggest performance upgrade your React app gets this year.&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>frontend</category>
      <category>performance</category>
    </item>
    <item>
      <title>How I Cut Docker Build Time in Half Using Savepoints — And Built a CLI Tool in Go</title>
      <dc:creator>Nour Mohamed Amine</dc:creator>
      <pubDate>Wed, 30 Apr 2025 01:50:56 +0000</pubDate>
      <link>https://forem.com/zeflq/how-i-cut-docker-build-time-in-half-using-savepoints-and-built-a-cli-tool-in-go-5g9a</link>
      <guid>https://forem.com/zeflq/how-i-cut-docker-build-time-in-half-using-savepoints-and-built-a-cli-tool-in-go-5g9a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;“Do I really have to rebuild from scratch… again?”&lt;br&gt;&lt;br&gt;
That was the thought that finally pushed me over the edge.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🚨 The Problem: Rebuilding the Unchanged
&lt;/h2&gt;

&lt;p&gt;If you’ve ever worked with a long &lt;code&gt;Dockerfile&lt;/code&gt; in CI/CD, you know this pain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You touch a line at the bottom
&lt;/li&gt;
&lt;li&gt;Docker cache misses (because the base layers are invalidated)
&lt;/li&gt;
&lt;li&gt;CI rebuilds everything — &lt;code&gt;apt update&lt;/code&gt;, &lt;code&gt;npm ci&lt;/code&gt;, &lt;code&gt;go mod download&lt;/code&gt;... the works&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;⏱️ Time wasted.
&lt;/li&gt;
&lt;li&gt;💰 Resources burned.
&lt;/li&gt;
&lt;li&gt;⚠️ Productivity gone.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Caching helps, but it's finicky across CI environments and can break easily.&lt;/p&gt;

&lt;p&gt;What I wanted was &lt;strong&gt;intentional, semantic checkpoints&lt;/strong&gt; in my Dockerfile.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 The Idea: Savepoints as Named Build Layers
&lt;/h2&gt;

&lt;p&gt;So I built &lt;strong&gt;Dockpoint&lt;/strong&gt; — a CLI that turns your Dockerfile into an intelligent, incrementally buildable script.&lt;/p&gt;

&lt;p&gt;With Dockpoint, you annotate your Dockerfile like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# savepoint: base&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:20&lt;/span&gt;

&lt;span class="c"&gt;# savepoint: deps&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm ci

&lt;span class="c"&gt;# savepoint: app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "index.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each &lt;code&gt;# savepoint: name&lt;/code&gt; becomes a &lt;strong&gt;named layer&lt;/strong&gt; that Dockpoint can build, tag, reuse, or skip in CI pipelines.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔧 Want to build only up to the &lt;code&gt;deps&lt;/code&gt; step?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dockpoint build-savepoint deps &lt;span class="nt"&gt;-t&lt;/span&gt; docker.io/your/app:deps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  📦 Want to build all steps and push them as incremental images?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dockpoint build-savepoint &lt;span class="nt"&gt;-t&lt;/span&gt; docker.io/your/app:1.0.0 &lt;span class="nt"&gt;--push&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ✨ The Magic: Content-Based Tagging (Using Hashing)
&lt;/h2&gt;

&lt;p&gt;Dockpoint doesn’t rely on Docker’s fragile cache alone.&lt;/p&gt;

&lt;p&gt;It hashes the Dockerfile lines used for each savepoint and creates a tag like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker.io/your/app:deps-14f95d20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If your &lt;code&gt;deps&lt;/code&gt; block changes → &lt;strong&gt;new tag&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;If it hasn’t changed → &lt;strong&gt;Dockpoint skips building&lt;/strong&gt; and reuses the layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ Your CI/CD becomes &lt;strong&gt;fast&lt;/strong&gt;, &lt;strong&gt;predictable&lt;/strong&gt;, and &lt;strong&gt;cache-safe&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ The Architecture (A Clean Go CLI)
&lt;/h2&gt;

&lt;p&gt;Yes — I built this in &lt;strong&gt;Go&lt;/strong&gt; (my first Go project).&lt;/p&gt;

&lt;p&gt;Dockpoint is written using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧼 &lt;strong&gt;Clean Architecture&lt;/strong&gt; (application, domain, infrastructure)
&lt;/li&gt;
&lt;li&gt;🐍 &lt;strong&gt;Cobra&lt;/strong&gt; for CLI
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;GoReleaser&lt;/strong&gt; for packaging (multi-arch, Homebrew-ready)
&lt;/li&gt;
&lt;li&gt;🤖 &lt;strong&gt;GitHub Actions&lt;/strong&gt; for CI
&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Codecov&lt;/strong&gt; for coverage tracking&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 One Command. Smart Layers.
&lt;/h2&gt;

&lt;p&gt;Dockpoint gives you a smarter docker build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dockpoint build-savepoint app &lt;span class="nt"&gt;-t&lt;/span&gt; docker.io/you/app:1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Tags each savepoint with its hash
&lt;/li&gt;
&lt;li&gt;Pushes final image cleanly
&lt;/li&gt;
&lt;li&gt;Reuses existing layers when possible
&lt;/li&gt;
&lt;li&gt;Speeds up your pipeline&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🎯 Why I Built This (And Why You Might Need It)
&lt;/h2&gt;

&lt;p&gt;This started with a single itch:&lt;br&gt;&lt;br&gt;
&lt;strong&gt;“Why are we rebuilding what didn’t change?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now Dockpoint has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Deterministic layer tagging
&lt;/li&gt;
&lt;li&gt;🔍 Savepoint validation
&lt;/li&gt;
&lt;li&gt;🌐 Cross-platform support
&lt;/li&gt;
&lt;li&gt;🧪 A clean, tested CLI written from scratch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re tired of Dockerfiles being dumb scripts with no structure,&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Dockpoint gives you structure — without changing Docker at all.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📥 Try Dockpoint
&lt;/h2&gt;

&lt;p&gt;Check it out:&lt;/p&gt;

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




&lt;h3&gt;
  
  
  🧪 Install
&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;# Homebrew (coming soon)&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;zeflq/tap/dockpoint

&lt;span class="c"&gt;# Or use GitHub Releases&lt;/span&gt;
curl &lt;span class="nt"&gt;-Lo&lt;/span&gt; dockpoint https://github.com/zeflq/dockpoint/releases/latest/download/dockpoint_linux_amd64.tar.gz
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; dockpoint_linux_amd64.tar.gz
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x dockpoint
./dockpoint &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ❤️ Final Thought
&lt;/h2&gt;

&lt;p&gt;This is my first Go project — and it made me fall in love with the language.&lt;br&gt;&lt;br&gt;
It’s fast, easy to compile, cross-platform, and perfect for tools like this.&lt;/p&gt;

&lt;p&gt;If Dockpoint saves you even &lt;strong&gt;one build cycle&lt;/strong&gt;, it’s worth it.&lt;br&gt;&lt;br&gt;
And if you want to help me polish &lt;code&gt;v1.1&lt;/code&gt; — &lt;strong&gt;PRs are welcome!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>cicd</category>
      <category>go</category>
    </item>
  </channel>
</rss>
