<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Mark&#39;s Dev Blog</title>
    <link>https://blog.isquaredsoftware.com/index.xml</link>
    <description>Recent content on Mark&#39;s Dev Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <lastBuildDate>Thu, 07 May 2026 15:00:00 -0500</lastBuildDate>
    <atom:link href="https://blog.isquaredsoftware.com/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>My Thoughts on AI, Part 2: Agent Setup, Workflow, and Tools</title>
      <link>https://blog.isquaredsoftware.com/2026/05/ai-thoughts-part-2-agent-workflow-tools/</link>
      <pubDate>Thu, 07 May 2026 15:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2026/05/ai-thoughts-part-2-agent-workflow-tools/</guid>
      <description>

&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Hopefully you&#39;ve already read &lt;a href=&#34;https://blog.isquaredsoftware.com/2026/05/ai-thoughts-part-1-fears-opinions-journey/&#34;&gt;Part 1: Fears, Opinions, and Mental Journey&lt;/a&gt; so you understand how I ended up with this mindset and approach. Or maybe you saw how long it was and just immediately bailed out :) Welcome either way.&lt;/p&gt;

&lt;p&gt;Part 1 was the braindump. Story, thoughts, feelings.&lt;/p&gt;

&lt;p&gt;Here&#39;s the part that probably more of you are interested in :) What my actual agent setup and dev workflow looks like. How I approach using AI for writing code, what tools I use, how I have them configured.&lt;/p&gt;

&lt;p&gt;You can see a cleaned-up version of my config at &lt;a href=&#34;https://github.com/markerikson/opencode-config-example&#34;&gt;https://github.com/markerikson/opencode-config-example&lt;/a&gt; - follow along in that repo for the pieces as I describe them here.&lt;/p&gt;

&lt;p&gt;As I said in Part 1: I am not trying to sell anything, change anyone&#39;s mind, or say I am an expert. I don&#39;t have the answers.&lt;/p&gt;

&lt;p&gt;BUT I DO HAVE SOME OPINIONS NOW! :) I&#39;m not saying that &lt;em&gt;everybody&lt;/em&gt; should follow them, but this is where I&#39;ve landed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#agent-setup-overview&#34;&gt;Agent Setup Overview&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#agent-opencode-and-codenomad&#34;&gt;Agent: OpenCode and CodeNomad&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#model-opus-4-6&#34;&gt;Model: Opus 4.6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#ide-vcs-vs-code-and-fork&#34;&gt;IDE / VCS: VS Code and Fork&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#daily-development-workflow&#34;&gt;Daily Development Workflow&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#parent-orchestrator-session-for-project-management&#34;&gt;Parent Orchestrator Session for Project Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#subtasks-for-development&#34;&gt;Subtasks for Development&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#opencode-config&#34;&gt;OpenCode Config&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#permissions-management&#34;&gt;Permissions Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#file-reads&#34;&gt;File Reads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#code-structure-and-search&#34;&gt;Code Structure and Search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#context-management&#34;&gt;Context Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#session-history-and-search&#34;&gt;Session History and Search&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#dev-plans-repo-and-management-scripts&#34;&gt;Dev Plans Repo and Management Scripts&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#plan-management-issues&#34;&gt;Plan Management Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#personal-dev-plans-repo&#34;&gt;Personal Dev Plans Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#workflow-artifacts&#34;&gt;Workflow Artifacts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#devplans-ts-automation-script&#34;&gt;&lt;code&gt;devplans.ts&lt;/code&gt; Automation Script&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#progress-updates-and-subtask-handoffs&#34;&gt;Progress Updates and Subtask Handoffs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#agents-md&#34;&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#commands-and-skills&#34;&gt;Commands and Skills&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#project-setup&#34;&gt;Project Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#progress-and-subtask-management&#34;&gt;Progress and Subtask Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#task-tracking&#34;&gt;Task Tracking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#other-commands&#34;&gt;Other Commands&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#other-skills&#34;&gt;Other Skills&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#config-improvement-process&#34;&gt;Config Improvement Process&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#potential-future-workflow-improvements&#34;&gt;Potential Future Workflow Improvements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;agent-setup-overview&#34;&gt;Agent Setup Overview&lt;/h2&gt;

&lt;h3 id=&#34;agent-opencode-and-codenomad&#34;&gt;Agent: OpenCode and CodeNomad&lt;/h3&gt;

&lt;p&gt;I&#39;ve settled on &lt;a href=&#34;https://opencode.ai/&#34;&gt;OpenCode&lt;/a&gt; as my agent of choice.&lt;/p&gt;

&lt;p&gt;I quickly decided I couldn&#39;t use TUIs for any development work. I&#39;ve always been a GUI / IDE user anyway. I briefly &lt;em&gt;tried&lt;/em&gt; both Claude Code and OpenCode TUIs, and bounced off &lt;em&gt;hard&lt;/em&gt;. It&#39;s not that I am against terminals or CLI tools, I use a lot of them! But I also like having multiple tabs, my choice of coding font, syntax highlighting, and even just straightforward copy/paste abilities. Maybe I gave up too quickly, but I really struggled to get any of the TUIs to do that.&lt;/p&gt;

&lt;p&gt;I know Claude Code is the market leader for coding agent. Maybe if I gave it another shot I&#39;d find some use out of it.&lt;/p&gt;

&lt;p&gt;On the other hand, I&#39;ve always been enough of a tinkerer that I do customize my tech and tool setups. Yeah, I&#39;m a lifelong Windows user, but I&#39;ve got a comprehensive suite of tools and techniques and customizations I&#39;ve built up over the years. I use Android because I want to fiddle and customize and configure the system the way I want it.&lt;/p&gt;

&lt;p&gt;OpenCode fit that bill when I tried it. It works well for me, and I&#39;m happy with it.&lt;/p&gt;

&lt;p&gt;So if I&#39;m not using the TUI, what&#39;s the alternative?&lt;/p&gt;

&lt;p&gt;I found a great third-party OpenCode web UI called &lt;a href=&#34;https://github.com/NeuralNomadsAI/CodeNomad&#34;&gt;CodeNomad&lt;/a&gt;. Tried it, loved it, works &lt;em&gt;great&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;My personal laptop is all Windows, but my day job is WSL within Windows. I can start CodeNomad&#39;s server from within the WSL environment, browse to the web UI from the Windows side, and not have to deal with any cross-platform filesystem limitations.&lt;/p&gt;

&lt;p&gt;I can have multiple sessions open in one browser tab (with a tabbed UI inside of the page), or have multiple browser tabs talking to the same server. I get full GUI copy and paste, good tool and edit/diff views, and a lot more.&lt;/p&gt;

&lt;p&gt;So, I now am actually doing my primary development there in CodeNomad. Not an IDE.&lt;/p&gt;

&lt;h3 id=&#34;model-opus-4-6&#34;&gt;Model: Opus 4.6&lt;/h3&gt;

&lt;p&gt;We primarily use Anthropic models at work. Honestly I&#39;ve never even tried Gemini / Codex / GPT-whatever / Kimi / etc. I&#39;ve really only used Opus and Sonnet.&lt;/p&gt;

&lt;p&gt;Opus 4.5 and 4.6 have both produced great results for me. Sonnet is decent.&lt;/p&gt;

&lt;p&gt;There&#39;s probably a lot I&#39;m missing. I don&#39;t want to burn a lot of time trying out models and running evals every few days, or switching back and forth just to eke out another 1% gainzzz. That&#39;s fine.&lt;/p&gt;

&lt;p&gt;I just need something that works well enough for me and that I&#39;m comfortable with, and Opus 4.5/4.6 have fit that bill perfectly.&lt;/p&gt;

&lt;p&gt;(As of writing, I haven&#39;t tried out 4.7, and I&#39;m kinda scared to. Too many weird reports about its behavior.)&lt;/p&gt;

&lt;p&gt;Also worth noting that I&#39;m using via API, not Max plans.&lt;/p&gt;

&lt;h3 id=&#34;ide-vcs-vs-code-and-fork&#34;&gt;IDE / VCS: VS Code and Fork&lt;/h3&gt;

&lt;p&gt;I&#39;ve been using VS Code as my editor and IDE of choice for many years. It&#39;s not perfect, but it works.&lt;/p&gt;

&lt;p&gt;Ironically, I now use it more as a file and diff viewer than as an editor :) I mean, I &lt;em&gt;am&lt;/em&gt; writing this blog post itself in VS Code. But for daily dev work, I do the session driving in CodeNomad in the browser, and then I flip over to VS Code to review and commit the diff.&lt;/p&gt;

&lt;p&gt;Honestly I don&#39;t &lt;em&gt;like&lt;/em&gt; VS Code&#39;s Git panels and UI! They feel very awkward. The diff hunk staging view in particular is &lt;em&gt;bad&lt;/em&gt;, especially compared to other IDEs like WebStorm or purpose-built Git GUIs. (Think I saw they maybe made some improvements in the last couple VSC releases - I haven&#39;t updated lately.)&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://git-fork.com/&#34;&gt;Fork&lt;/a&gt; has been my Git GUI client of choice for the last few years. Excellent, absolutely worth it.&lt;/p&gt;

&lt;p&gt;The issue here is that all my work repos are inside the WSL environment. It&#39;s &lt;em&gt;technically&lt;/em&gt; possible to point Fork at a cross-platform WSL share of the repo folder, but the file changes tend to not refresh well, so I&#39;ve mostly fallen back to just doing Git diff operations in VS Code. I think there may be some Fork tweaks that make it work better in WSL - haven&#39;t dug into those. I do know there&#39;s some Linux-native Git GUIs out there, I just haven&#39;t spent time evaluating those lately either.&lt;/p&gt;

&lt;h2 id=&#34;daily-development-workflow&#34;&gt;Daily Development Workflow&lt;/h2&gt;

&lt;p&gt;My workflow is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A long-running &amp;quot;Orchestrator&amp;quot;-mode parent session with the overall context for the major development work that I&#39;m doing. This session&#39;s job is solely to spawn child subtasks where I do the real work interactively.&lt;/li&gt;
&lt;li&gt;Child subtasks dedicated to some subset of the actual work. This may be codebase research and exploration, feature planning, or actual code development. These are highly interactive - I spend all my time discussing, directing, and driving these subtasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core principles here are: &lt;em&gt;I&#39;m&lt;/em&gt; in control. I&#39;m the one who knows what I&#39;m working on and what I want to accomplish. &lt;em&gt;I&lt;/em&gt; decide what the tasks are, and how to accomplish them. &lt;em&gt;I&lt;/em&gt; decide when to move from research to implementation, when to keep digging further or pivot a session from the original goal to a side quest, and when a task is actually done. &lt;em&gt;I&lt;/em&gt; need to be mentally engaged, understand what is happening and why, review the code, and actually commit it when I&#39;m satisfied.&lt;/p&gt;

&lt;p&gt;Most of the time I have one active parent session, and 1-3 active subtask sessions. I do bounce between the active subtasks and context-switch. Normally these are all still part of the same actual workstream. I have tried running sessions for 2-3 different workstreams at the same time, and it&#39;s tough, so I mostly stick with one workstream at a time now.&lt;/p&gt;

&lt;p&gt;I&#39;m sure a lot of folks will say &amp;quot;but that&#39;s so slow, you could be moving so much faster!&amp;quot;.&lt;/p&gt;

&lt;p&gt;I know. That&#39;s the point :) I&#39;m intentionally choosing to limit the workflow to what I can manage in my own head, so that I am still fully mentally engaged and building my own understanding of the system.&lt;/p&gt;

&lt;p&gt;I also specifically aim to keep as many of the moving pieces as deterministic and scripted as possible, especially for things that &lt;em&gt;can&lt;/em&gt; be automated like file management tasks.&lt;/p&gt;

&lt;h3 id=&#34;parent-orchestrator-session-for-project-management&#34;&gt;Parent Orchestrator Session for Project Management&lt;/h3&gt;

&lt;p&gt;I start every new parent session by running my &lt;code&gt;/context&lt;/code&gt; command. This tells the agent to read &lt;code&gt;current-focus.md&lt;/code&gt; and the last 2-3 days worth of progress file entries. That way it has baseline knowledge of the current repo, recent work, and what I&#39;m actually working on.&lt;/p&gt;

&lt;p&gt;From there, I give specific instructions for whatever I&#39;m working on. This is usually several paragraphs of &amp;quot;here&#39;s the overall goal I&#39;m working towards today, here&#39;s what I&#39;m specifically trying to accomplish, here&#39;s how I want to get there&amp;quot;. Then I specifically instruct the orchestrator parent session to spawn one or more subtasks to do the actual work. It then sits and waits for those to complete.&lt;/p&gt;

&lt;p&gt;OpenCode subtasks are essentially async functions with a return value, where the subtask can return some message to the parent. However, the child often returns a response with the &lt;em&gt;initial&lt;/em&gt; result, but I then keep driving the subtask much further and do a lot more work, so the initial response doesn&#39;t capture the actual work accomplished. Another problem is that if I don&#39;t like what a subtask is doing and hit the &amp;quot;Stop&amp;quot; button in that session, it cancels the response to the parent and returns an empty value. The orchestrator has a bad habit of seeing that empty response and saying &amp;quot;oh, the child didn&#39;t complete, let me spawn another subtask to pick up where it left off&amp;quot;. I&#39;ve had to specifically instruct it &amp;quot;&lt;em&gt;never spawn more subtasks until explicitly told to do so&lt;/em&gt;!&amp;quot;&lt;/p&gt;

&lt;p&gt;My instructions for spawning a subtask are surprisingly lax in some ways. I&#39;ve done a bunch of work to give the orchestrator context on what I&#39;m doing, why, and what the next goal is. At that point, I often say &amp;quot;spawn a new subtask to....&amp;quot;, and leave most of the details up to the orchestrator. Sometimes I&#39;ll give fairly specific bullet points: &amp;quot;have the child read files A, B, and C for context. Then, come up with an initial plan to build this feature, and pause. I&#39;ll review and confirm implementation.&amp;quot; Other times, especially when the parent session has gone on for a while and the orchestrator has already spun up a half dozen child tasks for earlier steps, I might just say &amp;quot;yep, kick off phase 3&amp;quot;, but by that point I have high confidence that we&#39;re on the right track and there&#39;s an established pattern for what we&#39;re doing.&lt;/p&gt;

&lt;p&gt;I&#39;ve had some parent sessions last up to a couple weeks as I&#39;m focused on an ongoing effort. Other times it might be a fresh parent session each day. Either way, it&#39;s about the overall goal that I&#39;m working towards right now.&lt;/p&gt;

&lt;p&gt;Here&#39;s what a typical orchestrator session looks like - the tail end of the &lt;code&gt;/context&lt;/code&gt; being loaded, and my initial instructions for what I want to do in this session.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.isquaredsoftware.com/images/2026-05-thoughts-on-ai-part-2/CodeNomad-parentOrchestrator.png&#34; alt=&#34;CodeNomad - parent orchestrator&#34; /&gt;&lt;/p&gt;

&lt;h3 id=&#34;subtasks-for-development&#34;&gt;Subtasks for Development&lt;/h3&gt;

&lt;p&gt;Subtasks are where I do all the actual work.&lt;/p&gt;

&lt;p&gt;I let the orchestrator write up the full prompt for child subtasks. This is normally enough to get the task started, read a bunch of files, orient itself, and &amp;quot;get the full picture&amp;quot; :)&lt;/p&gt;

&lt;p&gt;The entire subtask session from there is highly interactive. If it&#39;s a research or planning session, I review the results and provide feedback on the output. If it&#39;s a coding session, I look at the initial plan for the changes and provide specific guidance and direction. I want to be very sure &lt;em&gt;both&lt;/em&gt; me and the agent understand what we&#39;re trying to do, why, and how. I&#39;ll provide guidance on specific techniques to use, ask questions about edge cases and ideas, have it expand my own thinking as much as possible. I only tell it &amp;quot;okay, go make these changes&amp;quot; once I&#39;m very sure about the intent.&lt;/p&gt;

&lt;p&gt;I usually try to keep an eye on the agent as it&#39;s making edits. I don&#39;t want to have to explicitly approve operations as it&#39;s running (and we&#39;ll talk about permissions management more later), but I at least want a sense of &lt;em&gt;what&lt;/em&gt; it&#39;s doing and if it looks like it&#39;s heading in the right direction. If not, I&#39;ll mash the &amp;quot;Stop&amp;quot; button and course-correct.&lt;/p&gt;

&lt;p&gt;Once the edits are done, I&#39;ll run / test / etc as needed. I also try to review the code as much as possible. &lt;em&gt;I&lt;/em&gt; then do the actual Git commits myself - staging, messages, commits.&lt;/p&gt;

&lt;p&gt;In a lot of ways this is &amp;quot;one developer workflow, but with extra steps&amp;quot;. Fair :) The speedup comes from the agent&#39;s ability to do the research for me, expand &amp;quot;here&#39;s what I want to do&amp;quot; into a plan for &lt;em&gt;how&lt;/em&gt; to do it, and then turn the &amp;quot;what and how&amp;quot; plan into specific code edits faster than I can. My fingers are fast, but my brain always had to work through the intent first. Here, I get to focus more on the intent and the desired behavior, and let the AI define most of the code-level changes to accomplish that.&lt;/p&gt;

&lt;p&gt;I frequently drive subtasks for extended periods of time. I &lt;em&gt;try&lt;/em&gt; to keep a given subtask on track, but sometimes I end up veering into side quests because it&#39;s easier to keep going here rather than start up a whole new subtask and load context for the freshly discovered problem all over again. Early on, this definitely led to hitting session context limits, which forced me to create commands to reload an entire session&#39;s transcript and run those after the entire session got auto-compacted. Now that I have the OpenCode Dynamic Context Plugin and better tools and instructions for reading files, it&#39;s rare for even an extended session to end up over 100K context. The agent is very proactive about compressing recent tool calls and discussions in order to keep context manageable, and this seems to produce much better results than a big-bang &amp;quot;summarize the entire session so far&amp;quot; compaction. (Granted, sometimes it &lt;em&gt;over&lt;/em&gt;-compresses recent chunks of the discussion and gets a bit confused on what we were doing :) )&lt;/p&gt;

&lt;p&gt;Once I am actually ready to wrap up a given subtask, I specifically manually trigger the two record keeping commands. &lt;code&gt;/progress&lt;/code&gt; tells the subtask to append a new &amp;quot;what did we accomplish?&amp;quot; entry to today&#39;s progress log file. &lt;code&gt;/subtask-complete&lt;/code&gt; writes a standalone version of that update with more details, suitable for the parent orchestrator session to read. I then switch back to the parent session and run &lt;code&gt;/subtask-resume&lt;/code&gt;, which reads all outstanding subtask handoff files so it knows what the N most recent subtasks accomplished. There&#39;s some duplication here, but I view it as &lt;code&gt;/progress&lt;/code&gt; is for the permanent record of what I did today, &lt;code&gt;/subtask-complete&lt;/code&gt; is the function return call results for the subtask to ensure the parent session knows where things stand.&lt;/p&gt;

&lt;p&gt;Here&#39;s a typical child subtask, in this case for working on Replay MCP&#39;s &lt;code&gt;ReactComponent&lt;/code&gt; MCP tool. First, the initial orchestrator-provided prompt:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.isquaredsoftware.com/images/2026-05-thoughts-on-ai-part-2/CodeNomad-childSubtask-01-prompt.png&#34; alt=&#34;CodeNomad - child subtask - initial prompt&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Then my responses to some of the agent&#39;s analysis and implementation suggestions:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.isquaredsoftware.com/images/2026-05-thoughts-on-ai-part-2/CodeNomad-childSubtask-02-discussion.png&#34; alt=&#34;CodeNomad - child subtask - implementation discussion&#34; /&gt;&lt;/p&gt;

&lt;p&gt;and finally nailing down some design decisions:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.isquaredsoftware.com/images/2026-05-thoughts-on-ai-part-2/CodeNomad-childSubtask-03-designDecisions.png&#34; alt=&#34;CodeNomad - child subtask - design decisions&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;opencode-config&#34;&gt;OpenCode Config&lt;/h2&gt;

&lt;p&gt;I have a &lt;em&gt;very&lt;/em&gt; customized OpenCode config and setup that I&#39;ve built to directly support that workflow.&lt;/p&gt;

&lt;h3 id=&#34;permissions-management&#34;&gt;Permissions Management&lt;/h3&gt;

&lt;p&gt;I don&#39;t YOLO or &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I run my agents directly on my own machines, no sandboxing. That also means that I need &lt;em&gt;some&lt;/em&gt; amount of safety checks on commands that get run.&lt;/p&gt;

&lt;p&gt;I &lt;em&gt;do&lt;/em&gt; want to eliminate as many unnecessary permissions prompts as I can. Even if I&#39;m watching and directly driving an agent session, it does get very annoying to see a bunch of permission prompts in the chat session blocking and waiting for my approval, when they&#39;re pretty clearly harmless.&lt;/p&gt;

&lt;p&gt;So, as I said in Part 1: determinism.&lt;/p&gt;

&lt;p&gt;I generated a custom OpenCode plugin to auto-approve as many Bash commands as reasonable based on the contents. It&#39;s decently sophisticated. There&#39;s a very long regex-based list of known safe commands and subcommands that get auto-approved, as well as a similar of known &lt;em&gt;dangerous&lt;/em&gt; commands that will get blocked. It actually does Bash parsing and tries to deal with heredocs and command substitutions.&lt;/p&gt;

&lt;p&gt;The bigger question is how this actually works with OpenCode at all.&lt;/p&gt;

&lt;p&gt;OpenCode refactored their whole permissions and plugin system a few months ago. There &lt;em&gt;was&lt;/em&gt; already a &lt;code&gt;&amp;quot;permission.ask&amp;quot;&lt;/code&gt; event trigger that allowed plugins to actually return a result, but in the refactor that got disabled. I filed an issue, other people have filed PRs, those haven&#39;t been merged. So, I&#39;ve been maintaining a small local fork of OpenCode that reimplements that functionality. That allows my plugin to actually manage permissions.&lt;/p&gt;

&lt;p&gt;I saw Claude Code now has a &amp;quot;not quite YOLO but let the agent self-approve commands&amp;quot; mode. That&#39;s nice, but why rely on more agent calls and more tokens when you can just parse and manage the commands deterministically? :)&lt;/p&gt;

&lt;p&gt;The big loophole here is dynamic scripts - &lt;code&gt;bun -e&lt;/code&gt;, &lt;code&gt;node -e&lt;/code&gt;, &lt;code&gt;python3 -c&lt;/code&gt;. Agents love those. They&#39;re really useful! Don&#39;t even bother writing a script file to &lt;code&gt;/tmp&lt;/code&gt;, just &lt;code&gt;bun -e &amp;quot;someCodeHere()&amp;quot;&lt;/code&gt; and get the results. Really useful when introspecting some data files.&lt;/p&gt;

&lt;p&gt;Obviously this means the agent could trivially smuggle through code that starts nuking folders or uploading my secrets to the mothership.&lt;/p&gt;

&lt;p&gt;In practice: I&#39;m not sure I&#39;ve seen my agents actually &lt;em&gt;try&lt;/em&gt; to run a command that would be truly destructive. I&#39;ve got these guardrails in place, and to some extent I haven&#39;t seen evidence that they&#39;re &lt;em&gt;necessary&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The permissions plugin does try to do some additional scanning of inline eval scripts for blatantly obvious calls like &lt;code&gt;unlink()&lt;/code&gt; and flags those entire commands for approval.&lt;/p&gt;

&lt;p&gt;It&#39;s a tradeoff I&#39;m happy with at this point.&lt;/p&gt;

&lt;h3 id=&#34;file-reads&#34;&gt;File Reads&lt;/h3&gt;

&lt;p&gt;OpenCode has a &lt;code&gt;Read&lt;/code&gt; tool, same as every other harness. It works. But agents default to just reading massive amounts of file text, over and over, both to learn the codebase and to remind themselves of what they&#39;ve seen already.&lt;/p&gt;

&lt;p&gt;I found a file read caching tool called &lt;a href=&#34;https://github.com/glommer/cachebro&#34;&gt;&lt;code&gt;cachebro&lt;/code&gt;&lt;/a&gt; that is available as an MCP. It checks file access times and hashes, and if the file hasn&#39;t changed since the last read, the tool returns a message saying &amp;quot;this hasn&#39;t changed&amp;quot;.&lt;/p&gt;

&lt;p&gt;I&#39;ve told my agent to default to using &lt;code&gt;cachebro&lt;/code&gt; for file reads. Unfortunately, the &lt;code&gt;cachebro&lt;/code&gt; MCP read tool doesn&#39;t interact with OpenCode&#39;s own &amp;quot;file last read&amp;quot; logic. That meant that if my agent tried to &lt;em&gt;write&lt;/em&gt; to a file, OpenCode would return an error saying &amp;quot;you must use the &lt;code&gt;Read&lt;/code&gt; tool first&amp;quot;, and then it would have to actually call &lt;code&gt;Read&lt;/code&gt; and it&#39;s all a waste of time and tool calls and tokens.&lt;/p&gt;

&lt;p&gt;So since I was already maintaining a small running fork of OpenCode to handle the &lt;code&gt;&amp;quot;permission.ask&amp;quot;&lt;/code&gt; event, I just added another commit to the fork that exposed OpenCode&#39;s &amp;quot;file access time&amp;quot; calls into the &lt;code&gt;Plugin&lt;/code&gt; interface. Then I built my own &lt;code&gt;cachebro&lt;/code&gt; plugin that watches for &lt;code&gt;cachebro&lt;/code&gt; MCP tool calls, and gets/sets the file read times so OpenCode knows that file&#39;s been read. Works great.&lt;/p&gt;

&lt;h3 id=&#34;code-structure-and-search&#34;&gt;Code Structure and Search&lt;/h3&gt;

&lt;p&gt;Per above, agents default to just &lt;code&gt;Read&lt;/code&gt; for everything. This is &lt;em&gt;awful&lt;/em&gt; for codebase exploration. Read 10-15 files just to trace dependencies and imports. Lots of extra wasted code text bloating the context. &lt;em&gt;Don&#39;t&lt;/em&gt; do this!&lt;/p&gt;

&lt;p&gt;I&#39;ve tried out a half-dozen different MCP tools that do full codebase parsing and provide tools to query structure, dependencies, outlines, and relevant chunks of code.&lt;/p&gt;

&lt;p&gt;Currently, I use &lt;a href=&#34;https://github.com/agentika-labs/grepika&#34;&gt;&lt;code&gt;grepika&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/jahala/tilth&#34;&gt;&lt;code&gt;tilth&lt;/code&gt;&lt;/a&gt; via MCP, and get great results. Highly recommended. I again have my &lt;code&gt;AGENTS.md&lt;/code&gt; with instructions to always use those as the primary file reading options, and I consistently see my agent using them and intelligently only loading relevant parts of files.&lt;/p&gt;

&lt;p&gt;I&#39;ve also previously tried &lt;a href=&#34;https://github.com/SimplyLiz/CodeMCP&#34;&gt;&lt;code&gt;ckb&lt;/code&gt;&lt;/a&gt; (CodeKnowledgeBase). It&#39;s got a massive set of tools for querying structure and blast radius, and I&#39;ve &lt;em&gt;wanted&lt;/em&gt; to use it, but I&#39;ve run into a few problems with indexing not working or tool calls timing out. Been playing with &lt;a href=&#34;https://github.com/CRJFisher/ariadne&#34;&gt;&lt;code&gt;ariadne&lt;/code&gt;&lt;/a&gt;, and I&#39;m constantly keeping an eye out for other codebase indexing tools.&lt;/p&gt;

&lt;h3 id=&#34;context-management&#34;&gt;Context Management&lt;/h3&gt;

&lt;p&gt;Per above, I do all my work exclusively in subagent sessions that I drive myself. This means my parent orchestrator session doesn&#39;t have any issues with maxing out the context window and needing to compact, but the child tasks do.&lt;/p&gt;

&lt;p&gt;I did pretty frequently hit 160-170K context and run into auto-compaction. I &lt;em&gt;hated&lt;/em&gt; it. The auto-compact summaries were &lt;em&gt;adequate&lt;/em&gt;, but inevitably there&#39;d be a bunch of details I cared about that would get lost.&lt;/p&gt;

&lt;p&gt;At first I built some dev scripts commands that would read the OpenCode session JSON files, filter out tool calls, and export the meaningful message contents out as a complete Markdown file. I built a &lt;code&gt;/session-reload&lt;/code&gt; command and skill that would force the agent to run the export command, read the entire exported transcript, and then pause.&lt;/p&gt;

&lt;p&gt;However, &lt;code&gt;grepika&lt;/code&gt; really reduced the amount of &lt;em&gt;code&lt;/em&gt; that was bloating context. That helped.&lt;/p&gt;

&lt;p&gt;Then I found the &lt;a href=&#34;https://github.com/Opencode-DCP/opencode-dynamic-context-pruning&#34;&gt;OpenCode Dynamic Context Pruning Plugin&lt;/a&gt;. Instead of waiting until your session is almost at full context and then doing a big summary of the &lt;em&gt;entire&lt;/em&gt; session as a replacement, which would be &lt;em&gt;really&lt;/em&gt; lossy, it gives your agent a &lt;code&gt;compress&lt;/code&gt; tool that it can use at will to compress and summarize &lt;em&gt;chunks&lt;/em&gt; of your session (like a bunch of exploration file reads, or earlier messages as you switch focus to a follow-up effort). This means there&#39;s more of the session messages that stay exactly as-is, there&#39;s less time spent compacting, and it&#39;s much rarer that one of my subtask sessions actually nears max context and has to compact everything just to reset.&lt;/p&gt;

&lt;p&gt;Ironically, I really found a great working combo of tools right before Anthropic shipped 1.0M context windows by default for everyone :) But seriously, in the last couple months since landing on this combo of tools and plugins, I find that even a very long-running technical subtask session rarely gets above 100K context, thanks to &lt;code&gt;grepika&lt;/code&gt; and &lt;code&gt;cachebro&lt;/code&gt; minimizing file reads and the agent happily compressing earlier chunks on the fly.&lt;/p&gt;

&lt;p&gt;I know this does mean you might have some cache invalidations that could bump cost because it&#39;s no longer just the one latest message at the end of the session that hasn&#39;t been seen by the server. But on the flip side, keeping the actual total context size smaller seems to pay off, and it&#39;s not like the agent is calling &lt;code&gt;compress&lt;/code&gt; every other turn.&lt;/p&gt;

&lt;p&gt;I &lt;em&gt;was&lt;/em&gt; using the &lt;a href=&#34;https://github.com/rtk-ai/rtk&#34;&gt;&lt;code&gt;rtk&lt;/code&gt;&lt;/a&gt; Rust CLI tool to automatically compress the output of tools like &lt;code&gt;grep&lt;/code&gt; to save on tokens. Unfortunately I saw too many cases where the agent got stuck in a loop trying to call &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;rtk grep&lt;/code&gt; would change the output too much, the agent got confused and tried again, and it just wasted time and tokens. So, eventually disabled &lt;code&gt;rtk&lt;/code&gt;. Might come back to it at some point.&lt;/p&gt;

&lt;h3 id=&#34;session-history-and-search&#34;&gt;Session History and Search&lt;/h3&gt;

&lt;p&gt;As mentioned, I initially built some custom scripts that would find the right session JSON files and export as separate Markdown transcripts with just the message text, no tool contents.&lt;/p&gt;

&lt;p&gt;OpenCode 1.2 switched to storing sessions internally in SQLite. I held off upgrading to 1.2 for a while because I had all my custom scripts and commands and didn&#39;t want to take the time to rewrite them. But, I finally did, and that actually simplified things quite a bit.&lt;/p&gt;

&lt;p&gt;My previous &lt;code&gt;/session-reload&lt;/code&gt; command told the agent &amp;quot;run the &lt;code&gt;export session&lt;/code&gt;-type command, look at the list of most recent sessions it gives you, find what you &lt;em&gt;think&lt;/em&gt; is the right Markdown file based on your own context and instructions, and read that&amp;quot;. Kind of awkward, left room for error.&lt;/p&gt;

&lt;p&gt;After rewriting my own session history plugin to read from OpenCode&#39;s own plugin/internal &lt;code&gt;client.session&lt;/code&gt; object, that all went away. Instead, I have a &lt;code&gt;reload_session&lt;/code&gt; tool that can just directly grab the list of messages from the plugin API using the session ID, filter, construct the Markdown contents, and directly return it as the tool call result. No file path or &amp;quot;match up the session&amp;quot; steps needed.&lt;/p&gt;

&lt;p&gt;It was also trivial to throw together &lt;code&gt;search_sessions&lt;/code&gt; and &lt;code&gt;read_session&lt;/code&gt; tools. They&#39;re currently pretty dumb and just do basic regex searches on session contents, no vector DBs or similarity scores or anything. But they&#39;re pretty useful even in that form.&lt;/p&gt;

&lt;h2 id=&#34;dev-plans-repo-and-management-scripts&#34;&gt;Dev Plans Repo and Management Scripts&lt;/h2&gt;

&lt;h3 id=&#34;plan-management-issues&#34;&gt;Plan Management Issues&lt;/h3&gt;

&lt;p&gt;During my initial couple months of using KiloCode, I found myself with the same proliferation of Markdown plan files that we&#39;ve all run into. So where do those go? The agent wants to default to writing them to the root of whatever repo you&#39;re working in. I made an effort to redirect it to write them to a &lt;code&gt;./docs&lt;/code&gt; folder, although in our main backend repo that already existed so I had to resort to &lt;code&gt;./docs/merikson&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Some of these plan files were worth committing or preserving, even if just for my own reference later. Others weren&#39;t.&lt;/p&gt;

&lt;p&gt;So where do the plan files go if this is a shared repo? I really didn&#39;t want to pollute a shared repo and commit history with dozens of my own personal semi-ephemeral plan files, or even the maybe-more-widely-useful architectural writeups.&lt;/p&gt;

&lt;h3 id=&#34;personal-dev-plans-repo&#34;&gt;Personal Dev Plans Repo&lt;/h3&gt;

&lt;p&gt;I decided the best option was to set up an entirely separate personal development doc knowledge base repo, just for myself. I dubbed it &lt;code&gt;dev-plans&lt;/code&gt;. That would give me a consistent place that I could store all my own Markdown artifacts and knowledge, commit it, save those for future reference, and not pollute the shared actual repo Git history.&lt;/p&gt;

&lt;p&gt;My &lt;code&gt;dev-plans&lt;/code&gt; repo structure is:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/dev-plans
  /personal
  /redux
    /$PROJECT1
      /architecture
      /features
      /progress-updates
      /research
      /subtask-handoffs
      current-focus.md
      QUIRKS.md
  /replay
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;current-focus.md&lt;/code&gt; is intermittently updated whenever I feel I&#39;m significantly shifting gears or focus on a repo, or completed a major chunk of work and the &amp;quot;what I&#39;m working on now&amp;quot; section should reflect that.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;QUIRKS.md&lt;/code&gt; is more of a project structure, known actual quirks or patterns, things to remember document.&lt;/p&gt;

&lt;p&gt;Every file other than the two fixed &lt;code&gt;current-focus.md&lt;/code&gt; and &lt;code&gt;QUIRKS.md&lt;/code&gt; files starts with a &lt;code&gt;YYYY-MM-DD&lt;/code&gt; prefix, such as &lt;code&gt;features/2026-05-06-some-feature.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ve got some archival scripts set up to move older documents from the flat folder structure into a nested &lt;code&gt;YYYY/MM&lt;/code&gt; structure to keep things a bit more readable, but haven&#39;t done much with that yet. I suspect I&#39;ll need some tools to help index the documents when I do that.&lt;/p&gt;

&lt;h3 id=&#34;workflow-artifacts&#34;&gt;Workflow Artifacts&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;architecture&lt;/code&gt; is meant to be longer-lived explorations of the codebase structure and patterns. Full-blown &amp;quot;what do we know about this project&amp;quot;, vertical &amp;quot;trace through this feature or data flow path&amp;quot;, reference material&lt;/li&gt;
&lt;li&gt;&lt;code&gt;features&lt;/code&gt; is WIP development plans. Here&#39;s the next thing we&#39;re going to build, we&#39;ve turned this into a concrete plan, use this as the basis&lt;/li&gt;
&lt;li&gt;&lt;code&gt;research&lt;/code&gt; is more of a grab bag. Sometimes it&#39;s scanning the codebase for concepts, other times it&#39;s research dives through Github and NPM for relevant concepts&lt;/li&gt;
&lt;li&gt;&lt;code&gt;progress-updates&lt;/code&gt; is the daily dated appended progress entries, &lt;code&gt;subtask-handoffs&lt;/code&gt; is the individual handoff files that get automatically archived as soon as they&#39;re read&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;devplans-ts-automation-script&#34;&gt;&lt;code&gt;devplans.ts&lt;/code&gt; Automation Script&lt;/h3&gt;

&lt;p&gt;I&#39;ve settled on using Bun with TS scripts for a lot of my personal needs and utilities.&lt;/p&gt;

&lt;p&gt;I&#39;ve tried to automate a lot of the common tasks I saw consistently pop up when interacting with the &lt;code&gt;dev-plans&lt;/code&gt; repo. I created &lt;code&gt;~/.config/opencode/scripts/devplans.ts&lt;/code&gt; and have fleshed it out over time with a variety of commands the agent uses all the time.&lt;/p&gt;

&lt;p&gt;Currently, that provides:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-ts&#34;&gt;/**
 * devplans.ts - Unified dev-plans CLI helper
 *
 * Commands:
 *   devplans info                      Get project mapping info (no side effects)
 *   devplans progress                  Get/create today&#39;s progress file (with late-night date logic)
 *   devplans progress list [n]         List n most recent progress files (default 3)
 *   devplans progress append [file]    Append entry from JSON file (deleted after read) or stdin
 *   devplans handoff create [slug]     Get path for new handoff file
 *   devplans handoff list              List files in pending/
 *   devplans handoff move [file]       Move from pending/ to completed/YYYY/MM/DD/
 *   devplans handoff consume           List, read, and move all pending handoffs
 *   devplans doc create &amp;lt;type&amp;gt; &amp;lt;slug&amp;gt;  Create dated doc (type: feature|arch|analysis|issue)
 *   devplans doc list &amp;lt;type&amp;gt; [n]       List docs of type (default 10)
 *   devplans session extract           Extract recent sessions, list newest 10
 *   devplans archive &amp;lt;folder&amp;gt;          Archive old files to folder/archive/YYYY/MM/DD/
 *   devplans archive --all             Archive all doc folders
 */
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These deterministic commands save a &lt;em&gt;lot&lt;/em&gt; of steps that the agent would have had to run itself to figure out what &lt;code&gt;dev-plans&lt;/code&gt; folder path matches the current repo, creating placeholder handoff files or documents, and updating progress docs. Most of my OpenCode slash commands start with some variation of &amp;quot;Run `bun dev-plans.ts some-command&amp;quot;.&lt;/p&gt;

&lt;p&gt;I also have a JSON file with folder mappings for my usual repo checkout paths in my personal laptop Windows and work laptop WSL environments. That way the script can just read those mappings and use the known paths.&lt;/p&gt;

&lt;p&gt;Per the Workflow section, I have a &lt;code&gt;/init&lt;/code&gt; command that helps me set up the scaffolding when adding a new project to &lt;code&gt;dev-plans&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&#34;progress-updates-and-subtask-handoffs&#34;&gt;Progress Updates and Subtask Handoffs&lt;/h3&gt;

&lt;p&gt;The most used subcommands are for &lt;code&gt;progress&lt;/code&gt; and &lt;code&gt;handoff&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;My original &lt;code&gt;/progress&lt;/code&gt; command told the agent to actually read today&#39;s progress file completely, then append a new section. This became an O(n^2)-type problem as the progress file kept growing over the course of a day. Just reading the file would bloat context, and this was especially bad when the subtask was already bordering on max session context.&lt;/p&gt;

&lt;p&gt;Now, &lt;code&gt;devplans progress&lt;/code&gt; prints JSON output with today&#39;s progress file path, but also creates a placeholder temp file and provides that path as well. The agent is instructed to overwrite the placeholder with its actual update, and then runs &lt;code&gt;devplans progress $TEMPFILE&lt;/code&gt;. The script then deterministically appends the new section to today&#39;s progress doc so the agent didn&#39;t have to read that file itself.&lt;/p&gt;

&lt;p&gt;Similarly, &lt;code&gt;/subtask-complete&lt;/code&gt; in the child tells it to run &lt;code&gt;devplans handoff create&lt;/code&gt; creates a target file path that the agent can write to, and then when I run &lt;code&gt;/subtask-resume&lt;/code&gt; in the orchestrator parent it runs &lt;code&gt;devplans handoff consume&lt;/code&gt; which auto-prints all pending handoff files immediately and then auto-archives them. This saves multiple steps of the agent fumbling around.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;devplans&lt;/code&gt; commands also intelligently handle dates and timestamps - automatically generating file paths with timestamps, figuring out today&#39;s progress file, and even assuming that any updates between midnight and 6 AM really belong on &amp;quot;the previous day&#39;s progress file&amp;quot; because it&#39;s likely I was working late into the night on something.&lt;/p&gt;

&lt;p&gt;There&#39;s still a lot of manual trigger behavior in here, and again I&#39;m good with that :)&lt;/p&gt;

&lt;h2 id=&#34;agents-md&#34;&gt;&lt;code&gt;AGENTS.md&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;My &lt;code&gt;AGENTS.md&lt;/code&gt; file is currently about 250 lines (and writing this post forced me to review it and do some reorganizing and condensation - it had gotten rather crufty).&lt;/p&gt;

&lt;p&gt;It starts with a short personal overview: who I am, day job at Replay, OSS work on Redux.&lt;/p&gt;

&lt;p&gt;Major sections include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interaction patterns: I specifically instruct the agent to be keep its responses short and direct, and avoid sycophancy. That includes both descriptions, and acknowledging my instructions.&lt;/li&gt;
&lt;li&gt;Thinking and problem solving: use critical thinking and be skeptical about assumptions and correctness; stop and rethink problems if stuck; do research, not trial-and-error; state plans and wait for confirmation to check assumptions and confirm user intent&lt;/li&gt;
&lt;li&gt;Git: &lt;em&gt;never&lt;/em&gt; commit, always stop and wait for me to review changes&lt;/li&gt;
&lt;li&gt;Personal tool environment: personal vs work laptop setups, path management, use Bun for scripting not Python&lt;/li&gt;
&lt;li&gt;Coding standards: TS usage, running tests, minimizing comments&lt;/li&gt;
&lt;li&gt;Code navigation: minimize context loading at all times; use &lt;code&gt;grepika&lt;/code&gt; and &lt;code&gt;tilth&lt;/code&gt; for navigating code, &lt;code&gt;cachebro&lt;/code&gt; for other file reads&lt;/li&gt;
&lt;li&gt;Tasks and behavior: manage todos and progress; be careful counting completion; manage current context&lt;/li&gt;
&lt;li&gt;Dev plans workflow: use &lt;code&gt;devplans.ts&lt;/code&gt; for file management; use of &lt;code&gt;QUIRKS.md&lt;/code&gt; and other rules files&lt;/li&gt;
&lt;li&gt;Subtask spawning and workflow rules: only spawn subtasks when told; verify completion;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I make no claims that my &lt;code&gt;AGENTS.md&lt;/code&gt; is optimized, correct, or a model to follow :) It&#39;s just what I&#39;ve evolved through my own usage.&lt;/p&gt;

&lt;h2 id=&#34;commands-and-skills&#34;&gt;Commands and Skills&lt;/h2&gt;

&lt;h3 id=&#34;project-setup&#34;&gt;Project Setup&lt;/h3&gt;

&lt;p&gt;I have some commands and skills for initial &lt;code&gt;dev-plans&lt;/code&gt; setup for a new repo - the usual &lt;code&gt;/init&lt;/code&gt; and &lt;code&gt;/architecture&lt;/code&gt;-type commands that scan the codebase, do a writeup of the details, do some initial architecture description docs, etc. Don&#39;t do those often, nothing special there.&lt;/p&gt;

&lt;h3 id=&#34;progress-and-subtask-management&#34;&gt;Progress and Subtask Management&lt;/h3&gt;

&lt;p&gt;As described above: &lt;code&gt;/progress&lt;/code&gt; specifically instructs the current session to create a new entry in today&#39;s progress log. &lt;code&gt;/subtask-complete&lt;/code&gt; tells a child subtask to record a separate handoff file that can be used as a &amp;quot;return value&amp;quot; to update the parent orchestrator session, &lt;code&gt;/subtask-resume&lt;/code&gt; has the parent session read all outstanding handoff files to know what got done.&lt;/p&gt;

&lt;h3 id=&#34;task-tracking&#34;&gt;Task Tracking&lt;/h3&gt;

&lt;p&gt;For most of my day to day work development, I&#39;ve gotten along fine without any explicit external task tracker. I&#39;m the one who knows what I&#39;m working on.&lt;/p&gt;

&lt;p&gt;For a couple projects, I&#39;ve tried using &lt;a href=&#34;https://github.com/dcramer/dex&#34;&gt;&lt;code&gt;dex&lt;/code&gt;&lt;/a&gt; as a lightweight external nested task tracking CLI. (Think &lt;code&gt;beads&lt;/code&gt;, but with way less slop.) It&#39;s worked pretty well! I&#39;ve got a skill that instructs the agent how to use &lt;code&gt;dex&lt;/code&gt; efficiently. I&#39;d have the orchestrator session run &lt;code&gt;dex&lt;/code&gt; commands to see where we stand in terms of task status, then pass &lt;code&gt;dex&lt;/code&gt; task IDs to a subtask and tell it to mark that task as in progress. Similar to avoiding having the agent do any Git commits, I told it not to mark any &lt;code&gt;dex&lt;/code&gt; tasks as complete until I explicitly instructed it to do so, and have a &lt;code&gt;/dex-complete&lt;/code&gt; command to help with that.&lt;/p&gt;

&lt;h3 id=&#34;other-commands&#34;&gt;Other Commands&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;/session-reload&lt;/code&gt; extracts the entire message history of the current session and returns it. Per above, this used to be writing it all to disk as a Markdown file, now it just constructs the transcript in memory from the DB entries and returns it as the tool result. I use this much less frequently now thanks to the OC Dynamic Context plugin and use of better file search tools - now that I have those I rarely get close to 150K+ context even in a long running subtask session.&lt;/p&gt;

&lt;p&gt;I wrote my own AI-powered code review tool called &lt;a href=&#34;https://github.com/markerikson/diffloupe&#34;&gt;&lt;code&gt;diffloupe&lt;/code&gt;&lt;/a&gt; that tries to compare stated change intent vs inferred change intent, and reviews for both bugs and intent mismatches. I have a &lt;code&gt;/code-review&lt;/code&gt; command that tells the agent to review the current changes by triggering &lt;code&gt;diffloupe&lt;/code&gt; and then report on the results.&lt;/p&gt;

&lt;h3 id=&#34;other-skills&#34;&gt;Other Skills&lt;/h3&gt;

&lt;p&gt;I do have a variety of skills available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;several for frontend design and UI work&lt;/li&gt;
&lt;li&gt;advanced TS patterns&lt;/li&gt;
&lt;li&gt;Replay CLI and MCP usage&lt;/li&gt;
&lt;li&gt;Architecture design and feature planning&lt;/li&gt;
&lt;li&gt;File / codebase search tools&lt;/li&gt;
&lt;li&gt;Assorted skills explaining how to use &lt;code&gt;diffloupe&lt;/code&gt;, &lt;code&gt;dex&lt;/code&gt;, and &lt;code&gt;gh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;config-improvement-process&#34;&gt;Config Improvement Process&lt;/h2&gt;

&lt;p&gt;After I did my initial config and workflow development efforts back in December, I&#39;ve alternated between periods of leaving it exactly as-is and focusing on just doing work, and getting annoyed with parts of the workflow and making improvements. Generally it&#39;s noticing that some particular pain point is becoming an issue - that I keep having to repeat a particular set of instructions, or that part of the workflow could be automated via &lt;code&gt;devplans.ts&lt;/code&gt;, or trying out a different codebase indexing plugin that I found. At that point I&#39;ll go spin up a new session inside my OpenCode config repo itself, talk through the problem space, and develop the changes accordingly.&lt;/p&gt;

&lt;p&gt;As a relevant example, just reading &lt;code&gt;AGENTS.md&lt;/code&gt; to write this post showed me how the content had gotten somewhat bloated and disorganized. So, I just started up a new session to review it, described my pain points, and the agent suggested a slimmed-down version that retained the key points, moved some of the detailed file tool usage instructions out to a separate skill, and better organized the &amp;quot;how to communicate&amp;quot; and &amp;quot;daily workflow&amp;quot; sections. Done.&lt;/p&gt;

&lt;h3 id=&#34;potential-future-workflow-improvements&#34;&gt;Potential Future Workflow Improvements&lt;/h3&gt;

&lt;p&gt;I&#39;m pretty happy with the tooling and workflow that I&#39;ve got right now. The one area where I feel I&#39;m lacking right now is that longer-term memory and context. The system I&#39;ve got is great for &amp;quot;what is the repo we&#39;re working in?&amp;quot; and &amp;quot;what&#39;s the current set of tasks?&amp;quot;, but I&#39;m finding I have to do a lot of work to dig up other recent sessions where some decision was made or a research document was generated, and feed those back into the current session. I need something that helps index or scan generated planning and progress files and dynamically feeds in relevant results to the current session, or MCP tools that the session can use to scan already-indexed files.&lt;/p&gt;

&lt;p&gt;I also don&#39;t have any kind of automatic &amp;quot;scan recent sessions for common patterns or corrections or learnings, and extract workflow improvements&amp;quot; system. I &lt;em&gt;do&lt;/em&gt; instruct agents to include possible learnings in the progress and handoff artifacts, and sometimes those trickle over to updates to &lt;code&gt;QUIRKS.md&lt;/code&gt;, but I feel there&#39;d be value in the automatic review process.&lt;/p&gt;

&lt;p&gt;I &lt;em&gt;am&lt;/em&gt; very happy with &lt;code&gt;grepika&lt;/code&gt; and &lt;code&gt;tilth&lt;/code&gt; for codebase exploration over just reading files manually. I can imagine it would be nice to somehow preload more of the codebase into a given session so it doesn&#39;t have to re-explore some of the same files each time&lt;/p&gt;

&lt;p&gt;Code review and ensuring intent are still hard. &lt;code&gt;diffloupe&lt;/code&gt; has been useful for doing some review checks. I intended to add my own full code review UI to it, but got distracted and never got back to that. I&#39;ve bookmarked a bunch of other code review tools and may still investigate some of those.&lt;/p&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;6000+ words, and this was with me deliberately &lt;em&gt;avoiding&lt;/em&gt; going into full amounts of technical detail :) So there you go.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&#34;https://github.com/markerikson/opencode-config-example&#34;&gt;the example config repo&lt;/a&gt; for the actual commands, scripts, and setup.&lt;/p&gt;

&lt;p&gt;No idea how many people will end up going through here, but as always, hope this info was useful!&lt;/p&gt;

&lt;p&gt;And more than anything else: whether you use AI to write all your code or write it by hand, I hope that you can find a workflow for yourself that is sustainable, maintainable, understandable, and &lt;em&gt;safely&lt;/em&gt; productive.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>My Thoughts on AI, Part 1: Fears, Opinions, and Mental Journey</title>
      <link>https://blog.isquaredsoftware.com/2026/05/ai-thoughts-part-1-fears-opinions-journey/</link>
      <pubDate>Thu, 07 May 2026 14:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2026/05/ai-thoughts-part-1-fears-opinions-journey/</guid>
      <description>

&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;This post will be tough to write. There&#39;s a lot of discourse and arguing about AI everywhere you look. I&#39;ve read it all. I don&#39;t want to get caught up in arguments, get misinterpreted, or be labeled with beliefs that don&#39;t apply.&lt;/p&gt;

&lt;p&gt;I am not e/acc or P(doom). I am a software engineer, I am a person, trying to figure this out same as everyone else.&lt;/p&gt;

&lt;p&gt;I am not trying to sell anything, change anyone&#39;s mind, or say I am an expert. I don&#39;t have the answers.&lt;/p&gt;

&lt;p&gt;I &lt;em&gt;do&lt;/em&gt; have thoughts, opinions, fears, excitement, and concerns. I&#39;ve shared a lot of them in private. Enough people have heard those thoughts and said they want to hear or read more about my opinions that it seems worth my time to write them up publicly. A lot of these aren&#39;t original to me. I don&#39;t claim to be a deep thinker. I &lt;em&gt;have&lt;/em&gt; read a lot, thought a lot, synthesized a lot.&lt;/p&gt;

&lt;p&gt;So, here&#39;s my story and opinions, from the heart, best as I can write them. So many points I could make and articles I could cite as references here, but this one&#39;s just me. My story, told my way. A lot of you are probably going to see the length and yell &amp;quot;TLDR&amp;quot; and nope right out of here, or throw it in an agent to summarize. That&#39;s fine. Take it for what it&#39;s worth. Maybe this helps someone else. (and if you want to skip to &lt;a href=&#34;https://blog.isquaredsoftware.com/2026/05/ai-thoughts-part-2-agent-workflow-tools/&#34;&gt;the tech workflow post&lt;/a&gt; there you go.)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#part-1-the-before-times&#34;&gt;Part 1: The Before Times&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#programming-is-life&#34;&gt;Programming Is Life&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#clouds-on-the-horizon&#34;&gt;Clouds on the Horizon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#ominous-signs&#34;&gt;Ominous Signs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#part-2-fear-doom-and-depression&#34;&gt;Part 2: Fear, Doom, and Depression&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#the-pivot&#34;&gt;The Pivot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-wilderness&#34;&gt;The Wilderness&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-tidal-wave&#34;&gt;The Tidal Wave&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#p-doom&#34;&gt;P(doom)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#depression&#34;&gt;Depression&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#part-3-reverse-engineering&#34;&gt;Part 3: Reverse Engineering&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#miami-sunshine&#34;&gt;Miami Sunshine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#flipping-the-bit&#34;&gt;Flipping The Bit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#part-4-taming-the-beast&#34;&gt;Part 4: Taming the Beast&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#architectural-research&#34;&gt;Architectural Research&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#mind-blown&#34;&gt;Mind. Blown.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#part-5-diving-in&#34;&gt;Part 5: Diving In&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#ramping-up&#34;&gt;Ramping Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#immer&#34;&gt;Immer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#nerd-sniped&#34;&gt;Nerd-Sniped&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#self-reflection&#34;&gt;Self-Reflection&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#part-6-liftoff&#34;&gt;Part 6: Liftoff&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#trust-factor&#34;&gt;Trust Factor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#gearing-up&#34;&gt;Gearing Up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-re-pivot&#34;&gt;The Re-Pivot&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#part-7-warp-speed&#34;&gt;Part 7: Warp Speed&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#pulling-it-all-together&#34;&gt;Pulling It All Together&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#pattern-matching&#34;&gt;Pattern Matching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#shipping-for-agents&#34;&gt;Shipping for Agents&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#part-8-so-what-do-i-think-today-anyway&#34;&gt;Part 8: So What Do I Think Today, Anyway?&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#most-of-my-fears-are-still-valid-and-so-are-you&#34;&gt;Most Of My Fears Are Still Valid, And So Are You&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#the-tiger-is-out&#34;&gt;The Tiger Is Out&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#gotta-go-fast&#34;&gt;Gotta Go Fast&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#oops-it-s-capitalism&#34;&gt;Oops It&#39;s Capitalism&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#maintainability-is-the-mindset&#34;&gt;Maintainability is the Mindset&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#but-non-determinism&#34;&gt;But Non-Determinism?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#is-this-actually-better&#34;&gt;Is This Actually Better?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#what-about-the-craft&#34;&gt;What About the Craft?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;part-1-the-before-times&#34;&gt;Part 1: The Before Times&lt;/h2&gt;

&lt;h3 id=&#34;programming-is-life&#34;&gt;Programming Is Life&lt;/h3&gt;

&lt;p&gt;I love programming. I love the problem solving, the thinking. Getting in a flow state, trance music cranked up, deep in the code, surfacing hours later and seeing that this feature didn&#39;t exist at the start of the day and now it does and it&#39;s all because I figured out how to do it. Debugging deeply. Trying to understand the guts of an unfamiliar system, figuring out where things were going wrong, finally nailing the tweak or architectural change that fixes the problem. Learning new tools, unlocking new capabilities.&lt;/p&gt;

&lt;p&gt;I&#39;ve been programming for 25+ years, over half my life. I cut my teeth in the early days of the Agile Manifesto. I read Joel Spolsky and that rewriting a system from scratch was a bad idea. I read the HN debates about how to interview programmers. I read the 8th Light and Uncle Bob discussions about &amp;quot;Software Craftsmanship&amp;quot; and honing our skills. I never spent time doing code katas, but clearly craft &lt;em&gt;mattered&lt;/em&gt;. Writing code the right way &lt;em&gt;mattered&lt;/em&gt;. It wasn&#39;t just about whether the code &lt;em&gt;ran&lt;/em&gt;. It was whether the code was &lt;em&gt;elegant&lt;/em&gt;, clean, readable, maintainable. &amp;quot;Make It Work, Make It Right, Make It Fast&amp;quot; became my mantra. &amp;quot;Tradeoffs&amp;quot; was my favorite keyword.&lt;/p&gt;

&lt;p&gt;I built my career on deep understanding. I firmly believe that &amp;quot;programming is building a mental model of the system&amp;quot;. That every programmer&#39;s job is really to understand the problem domain and the system they&#39;re working on, that you break down a new feature or bugfix by comparing it to your existing understanding of the system, and that at the end of a 6-hour coding session you&#39;ve not only written working code but you&#39;ve shaped a new and improved understanding of the existing system &lt;em&gt;plus&lt;/em&gt; the changes. That you learn the fundamentals of your tools, go into the next layer of abstraction, dig into unfamiliar code, learn on the fly.&lt;/p&gt;

&lt;p&gt;I believe in determinism. That pure functions aren&#39;t just an esoteric concept, but make code predictable and testable. That you &lt;em&gt;can&lt;/em&gt; understand a system, even if there&#39;s distributed pieces and timing problems and race conditions. That you &lt;em&gt;can&lt;/em&gt; solve a problem by taking the time to understand it, break it down, build the mental model, scientific method debug the solution, document it, maintain it. Redux wasn&#39;t just a way to manage data outside React, but a way to make the data flow predictable. That the Redux DevTools should show a meaningful human readable history of what happened in the application.&lt;/p&gt;

&lt;p&gt;And then came AI.&lt;/p&gt;

&lt;h3 id=&#34;clouds-on-the-horizon&#34;&gt;Clouds on the Horizon&lt;/h3&gt;

&lt;p&gt;Dunno when I first started hearing about using AI to write code. Probably somewhere in the GPT-2ish era. Surely read it somewhere on HN or Reddit.&lt;/p&gt;

&lt;p&gt;I think the first real examples I saw of actual AI-generated code were from Github Copilot as a VS Code extension. I&#39;d always been an IDE user, all the way back to the Visual C++ days. (yes yes I know some of you predate that considerably, same as folks who used Amigas and C64s predate my first 286 and DOS 3.3 usage. My story here.)&lt;/p&gt;

&lt;p&gt;IDE autocomplete is ancient tech. Whether it was VC++, Visual Studio C#, Eclipse and Java, or fine even you Vim/Emacs people with some custom plugin, we&#39;ve always been able to type &lt;code&gt;person.&lt;/code&gt; and see &lt;code&gt;firstName, lastName, age&lt;/code&gt; pop up in the autocomplete overlay. Simple and deterministic. Sometimes we rely on it too heavily, but no one can memorize all the available methods anyway.&lt;/p&gt;

&lt;p&gt;AI-powered &amp;quot;autocomplete&amp;quot;, though? That&#39;s... something different.&lt;/p&gt;

&lt;p&gt;I resisted at first. I didn&#39;t want a non-deterministic tool trying to offer &amp;quot;suggestions&amp;quot;. &lt;em&gt;I&lt;/em&gt; knew what I wanted to write. I didn&#39;t need some Statistical Word Generating Machine trying to somehow guess what I &lt;em&gt;might&lt;/em&gt; want to do next.&lt;/p&gt;

&lt;p&gt;My work journal says I finally gave in and decided to try Github Copilot in March 2023, and concluded: &amp;quot;It&#39;s... not awful? It&#39;s doing a decent job being a smarter Intellisense so far.&amp;quot;&lt;/p&gt;

&lt;p&gt;So I left it on. Got some use out of it. Two thirds of the time the suggestions were completely bogus, but at least it was limited to trying to suggest a couple lines of code at a time, maybe outlining a &lt;code&gt;for&lt;/code&gt; loop or something. Scoped. Readable. I could see the suggestions, I could ignore them, I only had to accept them if they actually &lt;em&gt;were&lt;/em&gt; what I was about to type in. Still under my control, my understanding.&lt;/p&gt;

&lt;p&gt;I do remember one incident where I was working on some perf optimizations for Reselect, and hijacking some of the unit test files to run perf tests. I hit Enter a couple times and paused... and it suddenly &amp;quot;suggested&amp;quot; an entire multi-paragraph comment about doing performance analysis and even referenced some repo that might not have existed yet, but was eerily relevant conceptually. That was kinda funny! ... and also scary.&lt;/p&gt;

&lt;h3 id=&#34;ominous-signs&#34;&gt;Ominous Signs&lt;/h3&gt;

&lt;p&gt;I started hearing about devs using this tech on a larger scale. Just repeatedly auto-accepting suggestions, or doing more. Seemed.... &lt;em&gt;wrong&lt;/em&gt;. It&#39;s non-deterministic. These things &lt;em&gt;hallucinate&lt;/em&gt;. Surely you can&#39;t rely on that for anything &lt;em&gt;real&lt;/em&gt;, right?&lt;/p&gt;

&lt;p&gt;I started seeing more and more evidence of AI-generated code and text popping up online. These frequently seemed to involve hallucinations. A couple incidents particularly stick out in my mind.&lt;/p&gt;

&lt;p&gt;In one case, a dev pinged me on Twitter saying that a link to my blog was producing 404. The URL was something akin to &lt;code&gt;https://blog.isquaredsoftware.com/YYYY/MM/blogged-answers-selectors-fetching/&lt;/code&gt;. Not quite that, but close enough. I checked, got a 404. Confused, I went to my blog repo, looked for that Markdown file, and it didn&#39;t exi..... waitaminute. I don&#39;t &lt;em&gt;remember&lt;/em&gt; ever having written a post with that kind of title. Where&#39;d they get that link? and sure enough, an LLM had utterly hallucinated a URL to my blog for &lt;em&gt;a post that did not exist&lt;/em&gt;. Gotten the URL format correct and everything. Completely wrong.&lt;/p&gt;

&lt;p&gt;Another time, a user asked in the Redux Discord channels about some Redux APIs, with code snippets... and those APIs also &lt;em&gt;did not exist&lt;/em&gt;. Asked, and sure enough, same thing. They asked an LLM, it gave them the snippet, they never checked and just believed the answers and then the suggested code was completely bogus.&lt;/p&gt;

&lt;p&gt;Small sample size, but examples of the larger pattern I was seeing. Clearly, LLMs could &lt;em&gt;not&lt;/em&gt; be trusted! Too many hallucinations.&lt;/p&gt;

&lt;p&gt;I think I even tried downloading a local LLM setup once or twice. Tried asking something about &amp;quot;Redux vs Flux&amp;quot;, took a very long time to generate tokens, and came up with a vaguely plausible sounding but completely incorrect answer paragraph.&lt;/p&gt;

&lt;p&gt;At this point every single indicator I had seen was telling me this technology simply could not be trusted. It&#39;s one thing to copy-paste some snippets off Stack Overflow and maybe the answer&#39;s wrong, but at least there it&#39;s a &lt;em&gt;person&lt;/em&gt; that wrote that. AI code would never reach any acceptable level of trustworthiness. It&#39;s non-deterministic! It hallucinates! There is just no possible way you can safely build maintainable systems on this kind of flawed foundation.&lt;/p&gt;

&lt;h2 id=&#34;part-2-fear-doom-and-depression&#34;&gt;Part 2: Fear, Doom, and Depression&lt;/h2&gt;

&lt;h3 id=&#34;the-pivot&#34;&gt;The Pivot&lt;/h3&gt;

&lt;p&gt;I had joined &lt;a href=&#34;https://replay.io&#34;&gt;Replay&lt;/a&gt; in spring 2022. Time travel debugging. It was the perfect fit. It matched everything I believed in in my career, every experience I had. Amazing team, brilliantly talented engineers. An impossible tool, already working. The hard part&#39;s done! We&#39;ve built time travel! We&#39;ve brought determinism to a non-deterministic world! A perfect product, blindingly obvious how useful it is. It&#39;ll save every web developer thousands of hours. I wish I&#39;d had this &lt;em&gt;years&lt;/em&gt; ago in my career. A codebase using React and Redux that I&#39;m already familiar with. No possible way this could go wrong. Won&#39;t be a rocket ship, but steady growth on the way and we&#39;ll succeed.&lt;/p&gt;

&lt;p&gt;We were wrong. &lt;em&gt;I&lt;/em&gt; was wrong.&lt;/p&gt;

&lt;p&gt;Turns out there&#39;s many aspects we never accounted for. Most devs are never taught how to debug. We learn it on the fly, by osmosis, as we go. No one approaches it scientifically. No one uses &lt;em&gt;existing&lt;/em&gt; graphical debugging tools like Chrome DevTools or VS Code&#39;s debugger. It&#39;s just spam some more console logs and reload the page. Trying to sell a more powerful graphical debugger just didn&#39;t work the way we assumed it would.&lt;/p&gt;

&lt;p&gt;I had spent all of 2023 getting to build amazing time-travel powered debugging tools. Our React and Redux DevTools integrations. &amp;quot;Jump to Code&amp;quot;, going from a click event to the React &lt;code&gt;onClick&lt;/code&gt; prop that handled it and pausing when it ran. I was a kid in a candy store, an entire toolbox of amazing time travel APIs at my fingertips. I was having a &lt;em&gt;blast&lt;/em&gt;. I was building incredible tools &lt;em&gt;now&lt;/em&gt;, but surely these were just the foundation for what we&#39;d get to build on top 10 years from now.&lt;/p&gt;

&lt;p&gt;But, turns out that just building the world&#39;s most amazing tech doesn&#39;t automatically bring in sales. We struggled. and in summer 2024, we pivoted.&lt;/p&gt;

&lt;p&gt;The pivot was a brutal blow. I never saw it coming. And not only were we throwing away the dream of time travel debugging, the dream that I&#39;d &lt;em&gt;believed&lt;/em&gt; in, the dream I wanted to spend the rest of my career building...&lt;/p&gt;

&lt;p&gt;we were pivoting to &lt;em&gt;AI&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In that moment I felt, quite literally and physically, like I&#39;d been punched in the gut.&lt;/p&gt;

&lt;p&gt;And I had the most &lt;em&gt;visceral&lt;/em&gt; gut reaction I can ever remember:&lt;/p&gt;

&lt;p&gt;&amp;quot;&lt;em&gt;HELL NO!&lt;/em&gt; I will &lt;em&gt;never&lt;/em&gt; work on &lt;em&gt;anything&lt;/em&gt; AI related!&amp;quot;&lt;/p&gt;

&lt;h3 id=&#34;the-wilderness&#34;&gt;The Wilderness&lt;/h3&gt;

&lt;p&gt;Post-pivot, Replay regrouped and tried to figure out what we could do. I busied myself working on our React analysis layer. Outside work, I spent a few months working on RTK Query&#39;s infinite query support.&lt;/p&gt;

&lt;p&gt;But at least those tasks were things I could do &lt;em&gt;by hand&lt;/em&gt;. With my own brain. &lt;em&gt;I&lt;/em&gt; dug through the ReactDOM artifacts and found the relevant functions to instrument. &lt;em&gt;I&lt;/em&gt; looked at the instrumented minified bundles and found the places where we were inserting callbacks the wrong way. &lt;em&gt;I&lt;/em&gt; went through the source for TanStack Query, Apollo, SWR, and built an understanding of infinite queries as a problem domain. &lt;em&gt;I&lt;/em&gt; took the contributed first draft implementation PR, tested it, worked out what pieces were missing, listed out the test cases we needed to handle. &lt;em&gt;I&lt;/em&gt; did the dozens of hours of grunt work to build the missing pieces, handle the edge cases, wrote the docs. &lt;em&gt;I&lt;/em&gt; shipped the new features.&lt;/p&gt;

&lt;p&gt;Me. My brain. My understanding.&lt;/p&gt;

&lt;p&gt;and it also kept me away from both &lt;em&gt;using&lt;/em&gt; AI to generate code, and from having to build &lt;em&gt;systems&lt;/em&gt; that wrapped AI. I didn&#39;t want to do &amp;quot;prompt engineering&amp;quot;. Didn&#39;t want to have to cajole an AI into &lt;em&gt;maybe&lt;/em&gt; producing valid output, or telling it &amp;quot;you&#39;re the world&#39;s greatest expert in $TOPIC&amp;quot;, or add &amp;quot;make no mistakes&amp;quot; to every instruction, or whatever stupid and ridiculous techniques of the week were getting thrown around on Twitter and HN. And I definitely didn&#39;t want to waste time writing AI infrastructure and plumbing. No SDKs, no API calls, &lt;em&gt;no AI app whatsoever&lt;/em&gt;.&lt;/p&gt;

&lt;h3 id=&#34;the-tidal-wave&#34;&gt;The Tidal Wave&lt;/h3&gt;

&lt;p&gt;But the onslaught of &amp;quot;AI!&amp;quot; everywhere was inescapable. And my reading habits didn&#39;t help.&lt;/p&gt;

&lt;p&gt;I know I&#39;m too addicted to social media. Lifelong information junkie. I &lt;em&gt;need&lt;/em&gt; to read. &lt;em&gt;Need&lt;/em&gt; to learn, to understand what&#39;s going on. I read anything that looks potentially relevant. I see technologies and concepts, label them, file them away in the back of my brain, and then months or years later I pattern-match and slap some relevant blocks together to build a solution that fits.&lt;/p&gt;

&lt;p&gt;And unfortunately that meant reading Twitter and HN. And every other article was about AI, LLMs, codegen, prompt engineering.&lt;/p&gt;

&lt;p&gt;By this time there was a constant drumbeat of articles insisting that &amp;quot;WRITING CODE WITH AI IS THE ONLY POSSIBLE FUTURE! YOU &lt;em&gt;MUST&lt;/em&gt; ADOPT THIS NOW! IF YOU AREN&#39;T LEARNING AND DOING THIS AND 10XING YOUR OUTPUT, YOU &lt;em&gt;WILL&lt;/em&gt; FALL BEHIND! EVEN IF YOU&#39;RE A SENIOR ENGINEER! YOU&#39;LL BE ECLIPSED BY JUNIORS! NO ONE WILL HIRE YOU! YOUR ENTIRE LIFE&#39;S WORK WILL BE A &lt;em&gt;WASTE&lt;/em&gt;! GET WITH THE PROGRAM &lt;em&gt;NOW&lt;/em&gt; OR YOU&#39;RE &lt;em&gt;DOOOOOOOMED&lt;/em&gt;!&amp;quot;&lt;/p&gt;

&lt;p&gt;Needless to say, this was &lt;em&gt;not&lt;/em&gt; good for my psyche.&lt;/p&gt;

&lt;p&gt;And it was worse when it came from authors who I could tell just from reading &lt;em&gt;were&lt;/em&gt; experienced engineers. It&#39;s one thing to look at a random Medium post and dismiss it three paragraphs in with &amp;quot;oh that person clearly has no clue what they&#39;re talking about&amp;quot;. But seeing apparently clueful senior engineers drinking the koolaid and screaming &amp;quot;ADAPT AND USE AI &lt;em&gt;OR DIE&lt;/em&gt;!&amp;quot; just made the spiral worse.&lt;/p&gt;

&lt;p&gt;I read plenty of counter-arguments. I bookmarked numerous posts from other senior engineers who, like myself, mourned the loss of their craft. That our whole way of life was being shredded, ripped away. I read them, saved them, felt the loss with my whole heart.&lt;/p&gt;

&lt;p&gt;And the drumbeats and onslaught just kept coming.&lt;/p&gt;

&lt;h3 id=&#34;p-doom&#34;&gt;P(doom)&lt;/h3&gt;

&lt;p&gt;By early 2025 I could feel this toxic deluge of info poisoning the thoughts in my brain. I had half-formed thoughts swirling around in the back of my head. I knew they were there. I knew what they were about. I just hadn&#39;t fully articulated them.&lt;/p&gt;

&lt;p&gt;And there was a lot of other things going on as well. Family concerns. Questions about work. Politics. The General State Of The World (&lt;em&gt;gestures wildly&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;And in March 2025, while chatting with a friend, I finally wrote out a whole bunch of bullet points describing my concerns about AI and what it was doing to the world and the software industry and my career.&lt;/p&gt;

&lt;p&gt;And then I stopped. I re-read what I&#39;d just written. Horrified.&lt;/p&gt;

&lt;p&gt;I feared what AI would do to the quality of the code we were collectively writing. How can you trust the output of a tool that randomly hallucinates? How can you build an understanding of a system when everyone&#39;s generating code, and no one&#39;s reading it? Software&#39;s already held together with duct tape and baling wire. Our shiny desktop apps and SAAS sites are badly architected and bug-ridden even in the best run team and project. If we use AI, won&#39;t it all fall apart and collapse? And am I going to have to spend all my time carefully scrutinizing every line of code just to make sure hallucinations and logic errors don&#39;t sneak through?&lt;/p&gt;

&lt;p&gt;I built my career on craftsmanship, on understanding, on careful work. I always felt like I never quite lived up to the ideals, that my code was always more slapped-together than it &lt;em&gt;ought&lt;/em&gt; to be. But at least I&#39;d taken the time to make it run, to figure out the solution, and to find the rough spots and sand them down. AI couldn&#39;t possibly match that understanding.&lt;/p&gt;

&lt;p&gt;I definitely didn&#39;t want to &lt;em&gt;use&lt;/em&gt; AI to write code. I &lt;em&gt;loved programming&lt;/em&gt;! That&#39;s the fun part! I&#39;d already switched back from being a team tech lead to just being an IC, because I had been reduced to only 50% coding time from being stuck in meetings, and that was &lt;em&gt;awful&lt;/em&gt;. I wanted to code! I feared using AI would turn me into some kind of weird PM / code reviewer hybrid, that all my time would be spent mindlessly clicking &amp;quot;LGTM&amp;quot; on my agent&#39;s output, that I wouldn&#39;t get to use my brain, that I wouldn&#39;t &lt;em&gt;learn&lt;/em&gt; anything, that my skills would atrophy. If I wanted to spend all my time managing I&#39;d have become a manager! Don&#39;t take away the task that I &lt;em&gt;love doing&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;I still didn&#39;t want to work on any kind of AI-related project. If I moved on and looked for a new job, would I even be able to find something that &lt;em&gt;wasn&#39;t&lt;/em&gt; AI? Every single opening and &amp;quot;we&#39;re hiring&amp;quot; post I saw was AI, AI, AI. I didn&#39;t think I could stomach &lt;em&gt;talking&lt;/em&gt; to a company that did AI-based products, much less deal with expectations for &lt;em&gt;using&lt;/em&gt; AI to write code.&lt;/p&gt;

&lt;p&gt;And what happens to the thousands of hours of work I&#39;ve put in building my craft? So many other fields of work were radically transformed by technology. Entire fields and industries changed overnight. Typists and secretaries disappeared with the PC. Lots of other examples. Was my own career about to become obsoleted? What does that mean for this industry? What about &lt;em&gt;my&lt;/em&gt; future jobs?&lt;/p&gt;

&lt;p&gt;And I feared for the rest of the industry as a whole. I had so many unique opportunities I was given in my career, from mentors and people who believed in me. I was given those opportunities because I&#39;d already demonstrated my efforts and skills, and was able to take advantage of them because I put in the work. Would AI destroy the pathway for juniors to build a career? Would it prevent them from even being able to build the core skills they &lt;em&gt;actually&lt;/em&gt; needed? Thinking, understanding, learning, reading code, building that mental model of a system.&lt;/p&gt;

&lt;p&gt;And then even further, what happens to our entire society? We&#39;ve seen ripple effects from everyone having phones at all times, social media overloading our brains with context collapse, teens sliding into depression from electronic bullying, students no longer learning to think and just throwing assignments into ChatGPT. What&#39;s the long-term prognosis of this on our whole &lt;em&gt;world&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;I wasn&#39;t worried about Skynet, or AGI, or gray goo wiping out humanity. I &lt;em&gt;was&lt;/em&gt; worried about AI&#39;s effects on society, industry, and my own career.&lt;/p&gt;

&lt;p&gt;And something in my brain snapped.&lt;/p&gt;

&lt;h3 id=&#34;depression&#34;&gt;Depression&lt;/h3&gt;

&lt;p&gt;I am a very mentally stable person. It&#39;s kind of ironic to write that. 3 years ago I would have written it and meant that there was &lt;em&gt;nothing&lt;/em&gt; wrong with me, at all, 100% completely perfectly mentally healthy. Then I had an &amp;quot;emotional awakening&amp;quot; thanks to a good friend asking pointed questions, realized I &lt;em&gt;did&lt;/em&gt; have a lot to work on, and dove head-first into therapy. It&#39;s been wonderful. I&#39;ve spent a massive amount of effort understanding myself, my feelings, my thoughts, my personal quirks, aspects of my brain and personality that caused me problems, building better relationships with those around me. And I&#39;m a much healthier and happier person now than I was earlier.&lt;/p&gt;

&lt;p&gt;But even before that, I&#39;ve always had a very stable emotional baseline. On a +-10 scale, I&#39;m generally 0 to +3 maybe? Very hard to get me upset. I snap back to a baseline &amp;quot;yup, things are fine&amp;quot; quickly. Between realist and optimist outlook. Never had to deal with &amp;quot;true&amp;quot; mental health issues.&lt;/p&gt;

&lt;p&gt;But staring at those bullet points, I suddenly questioned how I was doing. I remember explicitly thinking &amp;quot;Wait. I&#39;ve been &lt;em&gt;saying&lt;/em&gt; &#39;I&#39;m okay, there&#39;s just a lot going on around me right now&#39;. But... &lt;em&gt;am&lt;/em&gt; I &#39;okay&#39;? Have I been fooling myself? And... &lt;em&gt;oh&lt;/em&gt;. I&#39;m also dealing with family concerns, and other stuff going on in the world... oh no. Maybe I&#39;m &lt;em&gt;not&lt;/em&gt; &#39;okay&#39; after all.&amp;quot;&lt;/p&gt;

&lt;p&gt;And I suddenly found myself in this bizarre mini-depressive state. Something I&#39;ve &lt;em&gt;never&lt;/em&gt; experienced before.&lt;/p&gt;

&lt;p&gt;I don&#39;t want to make comparisons to other people&#39;s mental health struggles. I can only speak for myself here. For me, it was like my emotional outlook on life had suddenly gotten dropped to... like a -3 on that +-10 scale? I was functional. I wasn&#39;t curled up in a ball. But instead of going around just focused on life and work, or being excited about things, I was telling myself &amp;quot;I&#39;m.... &lt;em&gt;struggling&lt;/em&gt; right now. I&#39;m &lt;em&gt;trying&lt;/em&gt; to hang in there. Things are not good. They&#39;re &lt;em&gt;bad&lt;/em&gt;. It&#39;s all out of my control. We&#39;re all careening out of control. I&#39;m just trying to make it through atm. Trying to manage.&amp;quot;&lt;/p&gt;

&lt;p&gt;It was &lt;em&gt;not&lt;/em&gt; fun.&lt;/p&gt;

&lt;p&gt;I know many folks deal with much worse. All I can say is this was something I&#39;d never experienced before. And it was essentially all due to these fears about AI.&lt;/p&gt;

&lt;p&gt;And nothing I could do could change the fate of the world.&lt;/p&gt;

&lt;h2 id=&#34;part-3-reverse-engineering&#34;&gt;Part 3: Reverse Engineering&lt;/h2&gt;

&lt;h3 id=&#34;miami-sunshine&#34;&gt;Miami Sunshine&lt;/h3&gt;

&lt;p&gt;React Miami has always been one of my favorite conferences. Michelle, Rebecca, and Gabe have done an amazing job putting on a conf that is both a non-stop party, an incredible social event, and a great source of technical info.&lt;/p&gt;

&lt;p&gt;Over the last several years, confs have become my own major social outlet. I&#39;ve met so many wonderful people. I get to see other amazing speakers, teachers, and maintainers in the React ecosystem. I&#39;ve built lifelong friendships. I get to meet tons of people from so many industries and walks of life. I get to travel the world, see places I&#39;ve never been, have deep conversations about tech and life and so much more. I look forward to every conf I go to.&lt;/p&gt;

&lt;p&gt;And in early April 2025, I feared going to React Miami.&lt;/p&gt;

&lt;p&gt;I&#39;d just burned a ton of emotional energy early in the year with the effort to kill Create React App. There&#39;d been numerous intense debates over how to handle that and how to update the React docs. I&#39;d had public and private discussions, given feedback, posted PRs, written and thrown away posts. I was already mentally exhausted from that, &lt;em&gt;before&lt;/em&gt; this AI depression hit.&lt;/p&gt;

&lt;p&gt;Now that I was wandering around in a &amp;quot;I&#39;m just struggling to survive&amp;quot; mental daze, I didn&#39;t know if I&#39;d even &lt;em&gt;enjoy&lt;/em&gt; myself at React Miami. Had I burned bridges? Would I have any brain capacity left to think about the talks? Would I have any social energy to be able to be around people? I was genuinely questioning if I should even go.&lt;/p&gt;

&lt;p&gt;I went.&lt;/p&gt;

&lt;p&gt;And I&#39;m thankful I did :)&lt;/p&gt;

&lt;p&gt;React Miami Day 1 was pretty good. Lot of discussions and hangout time. Definitely felt low energy and &amp;quot;lousy&amp;quot;. But I&#39;d socialized, been around people, gotten through the day.&lt;/p&gt;

&lt;p&gt;Day 2, though. Wow.&lt;/p&gt;

&lt;p&gt;I&#39;d gotten enough sleep to have some energy. And Day 2 was nothing but non-stop conversations. So many great conversations.&lt;/p&gt;

&lt;p&gt;I&#39;ve learned to manage my social battery over the years. Usually by 8:30-9:00 I know it&#39;s hitting 0% and I need to go back to my room and chill. This time, I was talking until almost midnight. I was worn out, but it &lt;em&gt;felt good&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I got back to my room and was journaling. And as I was journaling that night, I realized I was tired of being stuck in this semi-depressive &amp;quot;struggling / doom and gloom&amp;quot; state. It sucked! It wasn&#39;t fun! I noted I wasn&#39;t making any forward progress, that I was just going in circles... and I &lt;em&gt;hate&lt;/em&gt; going in circles for anything. Stop &lt;em&gt;talking&lt;/em&gt; about Doing The Thing. Just &lt;em&gt;Do The Thing&lt;/em&gt; and get something done!&lt;/p&gt;

&lt;p&gt;So I decided I was done with whatever the hell this was. Let&#39;s move on.&lt;/p&gt;

&lt;p&gt;And somehow, with essentially a snap of my fingers, I snapped myself out of that semi-depressive mindset.&lt;/p&gt;

&lt;h3 id=&#34;flipping-the-bit&#34;&gt;Flipping The Bit&lt;/h3&gt;

&lt;p&gt;I honestly have no answer for this! I can&#39;t tell you how I did it. I&#39;ve told friends and they&#39;ve said &amp;quot;how &lt;em&gt;did&lt;/em&gt; you do that?&amp;quot; and I can&#39;t explain it.&lt;/p&gt;

&lt;p&gt;It&#39;s some combination of having done therapy, realizing I &lt;em&gt;could&lt;/em&gt; change my attitudes and how I feel about things, not wanting to be permanently stuck in a negative situation, and being ready to get back to moving ahead with life.&lt;/p&gt;

&lt;p&gt;I also realized that yes, there&#39;s an absurd number of things that are out of my control. Weather, politics, tech advancement, society, even many aspects of my job. If I spend all my time thinking about things I can&#39;t control, then no, of &lt;em&gt;course&lt;/em&gt; I&#39;m going to be worried, but also I literally &lt;em&gt;can&#39;t do anything about it&lt;/em&gt;! So, why not refocus back on the things I &lt;em&gt;can&lt;/em&gt; control. My brain, my life, my family, my friends, my hobbies, my career.&lt;/p&gt;

&lt;p&gt;And somehow I just hit the reset button and went right back to my standard emotional baseline and have been there ever since :)&lt;/p&gt;

&lt;p&gt;This didn&#39;t change any of the concerns I had. AI was still destroying the software industry. The world was still chaotic. I still didn&#39;t want to work on any AI project. And I sure absolutely &lt;em&gt;would not ever&lt;/em&gt; use AI to write code for me. Period. Red line. Uncrossable. Ain&#39;t gonna happen.&lt;/p&gt;

&lt;p&gt;I just didn&#39;t want to spend all my time walking around panicking about those things and the impending end of the world. So I didn&#39;t.&lt;/p&gt;

&lt;h2 id=&#34;part-4-taming-the-beast&#34;&gt;Part 4: Taming the Beast&lt;/h2&gt;

&lt;h3 id=&#34;architectural-research&#34;&gt;Architectural Research&lt;/h3&gt;

&lt;p&gt;I&#39;d spent the first few months of 2025 working on Replay&#39;s sophisticated React analysis instrumentation layer, enabling it to successfully instrument React 19 and extract timing data. Around May, I was tasked with refactoring a complex portion of our backend, which managed a tree of forked processes for executing and replaying the program being debugged. I had a decent grasp of the &lt;em&gt;rough&lt;/em&gt; shape of how our time travel processing worked, and had touched &lt;em&gt;some&lt;/em&gt; parts of the system, but not this section.&lt;/p&gt;

&lt;p&gt;The general task was to replace a bunch of module-scoped variables that made this a singleton with equivalent classes so that we could instantiate multiple analysis processes in parallel. Doable, but you definitely need to, yes, &lt;em&gt;understand the system&lt;/em&gt; to make the changes. So that would take time.&lt;/p&gt;

&lt;p&gt;I remember a teammate had actually tried to do some of this refactor via AI and put up a draft PR that was broken. I skimmed it, and saw that a large chunk of the actual code changes were really just threading OpenTelemetry &lt;code&gt;cx&lt;/code&gt; context objects through one function after another to enable proper traces. That was clearly a very mechanical set of refactoring. Maybe it was something I could just start doing myself, mindlessly, and start to learn this section of the codebase.&lt;/p&gt;

&lt;p&gt;I started doing a lot of that context refactoring myself. And that did teach me a lot about the files and the methods and their connections. More importantly, it got my brain woken up and engaged in the &amp;quot;writing code and focused&amp;quot; part of the work.&lt;/p&gt;

&lt;p&gt;I don&#39;t remember exactly when this happened, but somewhere around here, I took a big mental step:&lt;/p&gt;

&lt;p&gt;I decided I could at least &lt;em&gt;try&lt;/em&gt; using AI, to &lt;em&gt;explain&lt;/em&gt; some of this code to me.&lt;/p&gt;

&lt;p&gt;I was very cautious about it. I didn&#39;t want to install a CLI/TUI agent. I wanted to stay in VS Code. I&#39;d seen the KiloCode extension mentioned a few times on HN by its founder, so I decided to give it a shot.&lt;/p&gt;

&lt;p&gt;So I installed KiloCode (probably Sonnet 3.5 or 4.0 at the time), pointed it at our codebase, and asked it to generate some architectural walkthroughs of this section.&lt;/p&gt;

&lt;p&gt;.... and it did? and... they were actually kinda useful? and didn&#39;t have &lt;em&gt;blatantly&lt;/em&gt; obvious hallucinations? and they actually helped build my own mental diagram of how the pieces fit together?&lt;/p&gt;

&lt;p&gt;Huh.&lt;/p&gt;

&lt;p&gt;Okay. I guess this is something I could keep using. But for explanations only. I still gotta write the code. Just me. Hard red line that I will &lt;em&gt;never&lt;/em&gt; cross.&lt;/p&gt;

&lt;h3 id=&#34;mind-blown&#34;&gt;Mind. Blown.&lt;/h3&gt;

&lt;p&gt;August 26, 2025. Tuesday afternoon.&lt;/p&gt;

&lt;p&gt;I&#39;d originally planned to spend time with family, but plans got canceled. Could have gotten day job work done, but I was in a mood to do some Redux maintenance.&lt;/p&gt;

&lt;p&gt;I was trying to optimize some RTK Query internals. Unfortunately I also realized that we didn&#39;t have any &lt;em&gt;tests&lt;/em&gt; that covered the specific bits of logic I was fiddling with. Tests are important, especially for libraries. I knew I &lt;em&gt;needed&lt;/em&gt; to add tests before I made changes, so I could capture the existing behavior.&lt;/p&gt;

&lt;p&gt;But my brain was tired. Tests are code. I didn&#39;t &lt;em&gt;wanna&lt;/em&gt; write tests. That was more effort.&lt;/p&gt;

&lt;p&gt;And so my brain said &amp;quot;uh... what if we had KiloCode + Claude write those tests for us?&amp;quot;&lt;/p&gt;

&lt;p&gt;I pulled up KiloCode. I described the section of the RTK code I was working on. I said &amp;quot;I need a couple unit tests that cover these cases&amp;quot;. I dictated the logic, the setup, the conditions, and what file they should go into.&lt;/p&gt;

&lt;p&gt;And for the first time, I said &amp;quot;Go write those&amp;quot;, and hit Enter.&lt;/p&gt;

&lt;p&gt;.......... and a few seconds later it spit out 75 lines of test code.&lt;/p&gt;

&lt;p&gt;And I read those tests. Carefully. Every line. Every condition. It was exactly what I asked for.&lt;/p&gt;

&lt;p&gt;And I held my face in my hands and &lt;em&gt;wept&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Okay okay it wasn&#39;t &lt;em&gt;quite&lt;/em&gt; that bad :) But I was, truly and genuinely, shocked and mind-blown.&lt;/p&gt;

&lt;p&gt;Absolutely I had just crossed the line that I swore I&#39;d never cross. I&#39;d used an AI to generate code for me! I even wrote in my journal that &amp;quot;I feel a lot of concern over blurring my own ethical boundaries. but also I just got a bunch of work done I wouldn&#39;t have had the brainpower to do today otherwise. and making progress on RTK maintenance &lt;em&gt;is&lt;/em&gt; good for my psyche.&amp;quot;&lt;/p&gt;

&lt;p&gt;Rubicon. Crossed.&lt;/p&gt;

&lt;p&gt;And then it got worse? better? shocking-er? the next two days.&lt;/p&gt;

&lt;p&gt;Our backend depended on &lt;code&gt;node-lz4&lt;/code&gt; to compress artifacts for S3. Unfortunately that lib was long out of date and unmaintained, and also the only thing keeping us from upgrading to newer Node versions. I&#39;d repeatedly looked for alternatives, always found a rust-based &lt;code&gt;lz4-napi&lt;/code&gt; package, but &lt;code&gt;lz4-napi&lt;/code&gt; didn&#39;t have Node streaming support and we relied on that. Repeated this cycle every few months.&lt;/p&gt;

&lt;p&gt;Wednesday I looked at it and said: &amp;quot;could.... could &lt;em&gt;AI&lt;/em&gt; implement that streaming feature?&amp;quot;&lt;/p&gt;

&lt;p&gt;I cloned &lt;code&gt;node-lz4&lt;/code&gt; and &lt;code&gt;lz4-napi&lt;/code&gt;. Pointed KiloCode + Claude at the two repos. Fed in the previous issues and discussion. Asked. And it claimed &amp;quot;sure, that&#39;s doable&amp;quot;.&lt;/p&gt;

&lt;p&gt;I made it write out some kind of plan, starting with upgrading some Rust deps, and then building the Rust streaming internals before doing the JS wrappers.&lt;/p&gt;

&lt;p&gt;I hit Enter.&lt;/p&gt;

&lt;p&gt;......... aaaaand I watched with my jaw dropped open as it cranked away on upgrading Rust deps, built, tested, and then started cranking out the streaming code.&lt;/p&gt;

&lt;p&gt;you&#39;ve &lt;em&gt;got&lt;/em&gt; to be kidding me.&lt;/p&gt;

&lt;p&gt;I walked KiloCode through doing some cross-compat tests and other bits. and within a few hours, it had seemingly built the entire missing feature I&#39;d been waiting for. Unreal.&lt;/p&gt;

&lt;p&gt;It would later turn out the &amp;quot;streaming&amp;quot; part didn&#39;t work right, and the &lt;code&gt;lz4-napi&lt;/code&gt; maintainer had to turn down the PR. Totally fair.&lt;/p&gt;

&lt;p&gt;But... I didn&#39;t even &lt;em&gt;know&lt;/em&gt; Rust! I couldn&#39;t have even &lt;em&gt;tried&lt;/em&gt; to do this myself! And here was a (seemingly) working implementation! Just by prompting!&lt;/p&gt;

&lt;p&gt;And sure, I&#39;d &lt;em&gt;read&lt;/em&gt; dozens of articles about people running umpteen agents, and having agents do all this work for you automatically. I &lt;em&gt;thought&lt;/em&gt; I understood the concept. I thought I got it.&lt;/p&gt;

&lt;p&gt;But &lt;em&gt;seeing&lt;/em&gt; an agent just happily talking its way through making dozens of code edits, one after the other? Wow.&lt;/p&gt;

&lt;p&gt;Thursday. I had to add a new lint rule to our own internal custom TS-based linting system to check for invalid &lt;code&gt;data-testid&lt;/code&gt; uses. I understand all these concepts. ASTs, nodes, parsers. TS program loading, visitors. Babel traversals, &lt;code&gt;ts-morph&lt;/code&gt;. I know these ideas already. Okay, fine, I haven&#39;t worked on &lt;em&gt;our&lt;/em&gt; custom linting system, so I don&#39;t know the exact nuances of the AST libs we need to use here, but this is clearly something I &lt;em&gt;can&lt;/em&gt; do, I just gotta take the time to figure out what moving pieces we have available and how they fit together.&lt;/p&gt;

&lt;p&gt;...... or could I have AI do it for me?&lt;/p&gt;

&lt;p&gt;So I had KiloCode generate an architectural doc describing our custom linting setup: where it lived, moving pieces.&lt;/p&gt;

&lt;p&gt;Then I had it generate an empty lint rule skeleton and integrate it into the existing system.&lt;/p&gt;

&lt;p&gt;Then I had it add some checks for JSX syntax patterns and set up some tests. Then I had it add checks for some known internal component types, and some more edge cases and tests.&lt;/p&gt;

&lt;p&gt;And. It. &lt;em&gt;Worked&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Drat&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;d gotten more done in an hour and a half, with AI, then I could have possibly accomplished by myself. I&#39;d &lt;em&gt;maybe&lt;/em&gt; have found the relevant files and set up the initial scaffolding. Instead here I had an actually working first pass on the lint rule, with tests.&lt;/p&gt;

&lt;p&gt;Mind. Blown.&lt;/p&gt;

&lt;p&gt;So I regret to inform you that this AI code gen thing is, apparently, &lt;em&gt;useful&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Now&lt;/em&gt; what am I supposed to do with my entire worldview?&lt;/p&gt;

&lt;h2 id=&#34;part-5-diving-in&#34;&gt;Part 5: Diving In&lt;/h2&gt;

&lt;h3 id=&#34;ramping-up&#34;&gt;Ramping Up&lt;/h3&gt;

&lt;p&gt;Programmers love to build systems and tools. We build systems to build systems to build systems. Ask a programmer to write a blog post, and they&#39;ll spent a month building a blogging CMS from scratch before they write the first article. We customize our shell aliases, our IDEs, our toolsets, our workflows.&lt;/p&gt;

&lt;p&gt;I&#39;ve been down that rabbit hole. I know that feeling. I didn&#39;t want to go down that rabbit hole &lt;em&gt;here&lt;/em&gt;. Not yet.&lt;/p&gt;

&lt;p&gt;This blog is still on the same version of Hugo 0.17 that I chose when I started this blog in October 2016. It&#39;s simple. It works. It&#39;s fast. I have entirely too many demands on my time, too many things on my todo list, more things than I will ever get done. The last thing I need is to waste hours and days customizing my blog setup. So I&#39;ve tweaked the templates over the years, but intentionally never let myself get sucked into changing the build setup.&lt;/p&gt;

&lt;p&gt;I tried to apply that principle here. I was seeing dozens of &amp;quot;HOW TO AWESOMEMAXX YOUR AGENT BY FOLLOWING THESE 11 SUPERPROMPTS AND L33T SKILLZ!&amp;quot; articles every day. I was even bookmarking some of them! But I held off on actually &lt;em&gt;changing&lt;/em&gt; anything.&lt;/p&gt;

&lt;p&gt;I stayed with KiloCode and Claude (which I&#39;ll abbreviate as &amp;quot;KCC&amp;quot;). I did not try to mega-optimize my workflow. I allowed it to be inefficient. I needed to &lt;em&gt;discover&lt;/em&gt; how &lt;em&gt;I&lt;/em&gt; wanted to use AI.&lt;/p&gt;

&lt;h3 id=&#34;immer&#34;&gt;Immer&lt;/h3&gt;

&lt;p&gt;By pure coincidence, early September is when I started trying to optimize performance for the Immer immutable update library.&lt;/p&gt;

&lt;p&gt;And again I regret to inform you that AI was &lt;em&gt;really&lt;/em&gt; helpful here.&lt;/p&gt;

&lt;p&gt;I spent over 110 hours of my own free time in Sep-Oct working on Immer perf, and I used AI extensively through that process.&lt;/p&gt;

&lt;p&gt;I&#39;d used Immer since it came out. My first RTK prototypes were built around Immer since day 1. I&#39;m even quoted in the docs saying how much I love it. I knew the principles of how it worked. I&#39;d &lt;em&gt;glanced&lt;/em&gt; at the code once or twice. I definitely didn&#39;t &lt;em&gt;understand&lt;/em&gt; the code, at all.&lt;/p&gt;

&lt;p&gt;I downloaded the repos for Immer, Mutative, Limu, and Structura. I had KCC scan the READMEs and documentation and write up summaries describing what each library &lt;em&gt;claimed&lt;/em&gt; it was good and and how the alternatives compared themselves to Immer. I had it analyze the internal architecture of each library and write architecture docs describing implementation details, and highlighting places where the alternates took different approaches.&lt;/p&gt;

&lt;p&gt;I knew how to do perf profiling, but I&#39;d already had previous issues trying to find good ways to get properly sourcemapped perf traces for Node scripts. After figuring out I couldn&#39;t just have my perf benchmarks script import artifacts directly due to &lt;code&gt;process.env.NODE_ENV&lt;/code&gt; skewing results, I had to pre-bundle my benchmark script, but that made it hard to read results. KiloCode generated scripts for me that would post-process my perf traces and re-combine with sourcemaps.&lt;/p&gt;

&lt;p&gt;Those initial scripts at least told me which functions were hottest. I pointed KCC at those functions and it identified low-hanging fruit that could be optimized: some simple cachine, some bailouts.&lt;/p&gt;

&lt;p&gt;My next big task was porting Mutative&#39;s &amp;quot;notification callback&amp;quot; cleanup approach to Immer to replace its recursive finalization logic. I had KCC try that. It failed, three separate times. Just got lost in the changes. So I did it myself. By now I&#39;d at least started to internalize the structure and logic of Immer&#39;s codebase, so I was gaining understanding of the code.&lt;/p&gt;

&lt;p&gt;I got the notification architecture port changes in place, but a large chunk of the unit tests were failing. And here I did something else I had sworn I wouldn&#39;t ever do:&lt;/p&gt;

&lt;p&gt;I turned my brain off.&lt;/p&gt;

&lt;p&gt;I had KCC add a few dozen log lines to Immer&#39;s internals. Then I&#39;d run one test at a time, copy 500 lines of log spew from the console, paste into KCC, and beg &amp;quot;tell me what went wrong here and how do we fix it&amp;quot;.&lt;/p&gt;

&lt;p&gt;Frankly it went against everything I&#39;d always believed in! But this was also in the middle of a bunch of conference travel. And I just wanted to make forward progress, and get to the point where the tests &lt;em&gt;passed&lt;/em&gt;, and then I could see if this architectural change actually improved performance or not.&lt;/p&gt;

&lt;p&gt;So I did. And eventually the tests passed. And it worked! Not as big a perf improvement as I&#39;d hoped, but meaningful.&lt;/p&gt;

&lt;p&gt;And so I turned my brain back on. I looked at the outstanding diffs from the KCC fixes. And I either traced through to understand what the point was for that change, or in some cases, asked KCC to explain the rationale to me. I filled in the gaps in my understanding, completed my mental model of the system.&lt;/p&gt;

&lt;p&gt;After cleaning up a bunch of debug code, I moved on to analyzing why proxied array methods were horribly slow. Turns out even a &lt;code&gt;draft.filter()&lt;/code&gt; requires iterating and that hits all the &lt;code&gt;get&lt;/code&gt; traps, creating new proxies and requiring cleanup even if all you did was read from them. KCC helped port some of the array / patch generation logic from Mutative. It did get stuck a few times, did hallucinate a few fixes. I kept redirecting it, kept it on track, and eventually we got that working too.&lt;/p&gt;

&lt;p&gt;I filed the Immer PRs. Michel Weststrate released them. AI was instrumental in helping me do that.&lt;/p&gt;

&lt;p&gt;By the time I was done, I &lt;em&gt;had&lt;/em&gt; built a full understanding of Immer&#39;s codebase. I&#39;d say I&#39;m probably the second best expert on Immer&#39;s architecture and functionality, after Michel (and in some ways better now that I pushed all those changes).&lt;/p&gt;

&lt;h3 id=&#34;nerd-sniped&#34;&gt;Nerd-Sniped&lt;/h3&gt;

&lt;p&gt;During 2025, Replay was working on Replay Builder, an AI-powered app builder. I&#39;d looked at some of the RTK code we were generating, and it wasn&#39;t good :) I remember one app that had five separate data fetching files, with five separate patterns for managing the requests. There shouldn&#39;t have been &lt;em&gt;any&lt;/em&gt; of that, because it all should have been using RTK Query for the data fetching :)&lt;/p&gt;

&lt;p&gt;So I looked at that, and thought &amp;quot;wait, I can make it write better RTK code.&amp;quot;&lt;/p&gt;

&lt;p&gt;And I nerd-sniped myself &lt;em&gt;hard&lt;/em&gt; :)&lt;/p&gt;

&lt;p&gt;I spent the next few months building out an entire 100% deterministic custom codegen system. DB tables -&amp;gt; Hono routes -&amp;gt; RTKQ endpoints. Fully type-safe and comprehensive. Modified a couple example apps to prove out the patterns we needed. Built the codegen system. Updated the prebuilt blocks used by the app builder. And I did all that work with AI. Absolutely would have taken 3-5x as much time if I&#39;d had to do it by hand.&lt;/p&gt;

&lt;p&gt;But, uh... at some point you have to hook this up to the LLM so it knows how to use the new system.&lt;/p&gt;

&lt;p&gt;And I had previously sworn that I would &lt;em&gt;never&lt;/em&gt;, ever, spend time working on anything like &amp;quot;prompt engineering&amp;quot;. Or &amp;quot;AI SDK plumbing&amp;quot;.&lt;/p&gt;

&lt;p&gt;Then again, I&#39;d also sworn I would never use AI to generate code :) and here I was now using AI, so clearly &lt;em&gt;that&lt;/em&gt; line had vanished.&lt;/p&gt;

&lt;p&gt;So yeah, by the time I got around to the last phase of the project, I &lt;em&gt;was&lt;/em&gt; actually excited about hooking up the codegen system to the actual LLM. Updating the prompts, getting the tooling right. I wanted to see it all work together.&lt;/p&gt;

&lt;p&gt;I guess I just needed the right motivation, and a concrete example that wasn&#39;t abstract and wasn&#39;t something I feared.&lt;/p&gt;

&lt;h3 id=&#34;self-reflection&#34;&gt;Self-Reflection&lt;/h3&gt;

&lt;p&gt;I have a strong need to keep records about my life and what&#39;s going on. I&#39;ve journaled a lot over the years. Kept a daily work journal for over a decade. Lots of personal journaling the last few years. Blogging. Various other communications.&lt;/p&gt;

&lt;p&gt;In early December I was going back to re-read some of my old work journal entries to remind myself about some earlier projects. Got the idea that I could use LLMs to help auto-summarize some of the entries to roll up details on what I worked on and accomplished. That turned into a larger project. Had it generate some vertical summaries of things I worked on, growth as an engineer, where I succeeded, where I struggled.&lt;/p&gt;

&lt;p&gt;And then I had it pull together some &amp;quot;insights about myself&amp;quot;. And &lt;em&gt;that&lt;/em&gt; was a &lt;em&gt;fascinating&lt;/em&gt; document.&lt;/p&gt;

&lt;p&gt;I&#39;ve read plenty of articles about AI psychosis. People going crazy, thinking they&#39;ve unlocked the Great Secrets of the Universe. I value my mind. I refuse to fall into that trap.&lt;/p&gt;

&lt;p&gt;LLMs are, hand-waving, Statistical Word Generating Machines. I know, I know, that&#39;s a drastic over-simplification, the tech is far past that, I get it. My post. Work with me here.&lt;/p&gt;

&lt;p&gt;An LLM has no soul. It&#39;s not a person. No matter how many pronouns or personalities or &lt;code&gt;SOUL.md&lt;/code&gt; files you give it, &amp;quot;it&amp;quot; isn&#39;t actually intelligent. A set of words generated by an LLM carries no thought, no intent, no &lt;em&gt;purpose&lt;/em&gt; behind it. We attribute intelligence where there isn&#39;t any.&lt;/p&gt;

&lt;p&gt;And yet. Sometimes we look up, and we see a cloud, or the stars, and the shape has enough recognition that it means something to us.&lt;/p&gt;

&lt;p&gt;And so an LLM generated a bunch of words, about me. Who I am. How I think. My struggles. My quirks. My flaws. My strengths.&lt;/p&gt;

&lt;p&gt;And sometimes just seeing recognition and words &lt;em&gt;about&lt;/em&gt; ourselves, from outside our own brain, helps us realize something about who we are.&lt;/p&gt;

&lt;p&gt;This doc had a lot of very personal insights about myself. The specifics are important, and they&#39;re private. But with some of the ways I&#39;ve grown, and challenges I&#39;ve faced... I actually needed to read those. And yeah, I was bawling that night :)&lt;/p&gt;

&lt;p&gt;Not gonna claim this works for everyone, or even that it&#39;s a good idea. But yeah, throwing a bunch of my writing into a blender and pulling out summaries and insights &lt;em&gt;was&lt;/em&gt; useful for me.&lt;/p&gt;

&lt;h2 id=&#34;part-6-liftoff&#34;&gt;Part 6: Liftoff&lt;/h2&gt;

&lt;h3 id=&#34;trust-factor&#34;&gt;Trust Factor&lt;/h3&gt;

&lt;p&gt;You know the step change that happened in late 2025. Opus 4.5 was really the turning point. Even Sonnet 4.5 was a distinct improvement over earlier models.&lt;/p&gt;

&lt;p&gt;I still very carefully drove all the sessions (and I still do today). But more and more, the code I saw getting generated was... well, &lt;em&gt;valid&lt;/em&gt; at least. Maybe not always &lt;em&gt;good&lt;/em&gt;. Certainly not how &lt;em&gt;I&#39;d&lt;/em&gt; write it. But if I told it to build $THING with $APPROACH... it&#39;d pretty much do that. And sure, I&#39;d have to course-correct some. But not nearly as much as before. And the mistakes were more about intent or details. At some point I realized I wasn&#39;t even thinking about hallucinations any more.&lt;/p&gt;

&lt;p&gt;I&#39;d also been using Claude.ai for some personal Q&amp;amp;A sessions. Still cautiously. Then it occurred to me that because I was starting to trust the &lt;em&gt;code&lt;/em&gt; output of the models, I was also starting to trust the models in &lt;em&gt;other&lt;/em&gt; domains too.&lt;/p&gt;

&lt;p&gt;In a way it seemed like the opposite of the Gell-Mann Amnesia effect. We read news stories about our own domain, realize the reporter and news source have &lt;em&gt;no&lt;/em&gt; clue what they&#39;re talking about for our area of expertise, but still trust for other areas unthinkingly.&lt;/p&gt;

&lt;p&gt;Here... I didn&#39;t trust &lt;em&gt;any&lt;/em&gt; of it. And then I found myself starting to trust the code. Maybe it wasn&#39;t &lt;em&gt;good&lt;/em&gt;, but it &lt;em&gt;worked&lt;/em&gt; and did what I wanted. .... so did I trust model output for &lt;em&gt;other&lt;/em&gt; areas too? More and more, the answer was yes.&lt;/p&gt;

&lt;h3 id=&#34;gearing-up&#34;&gt;Gearing Up&lt;/h3&gt;

&lt;p&gt;By Christmas 2025, I was finally ready to go customize my workflow and setup. I&#39;d accumulated a few months of experience, figured out how &lt;em&gt;I&lt;/em&gt; wanted to use AI, and found a workflow pattern that worked for me. Now it was time to slap on all the bells and whistles and make this thing &lt;em&gt;scream&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I tried Claude Code. For about a day, tops. The VSC extension didn&#39;t work at all. Tried the TUI, and bounced off it &lt;em&gt;hard&lt;/em&gt;. Why would anyone want to use something stuck in a terminal?&lt;/p&gt;

&lt;p&gt;Tried OpenCode. Also tried the TUI. Pretty much the same result. Don&#39;t get me wrong, I spend a lot of time in terminals, but I&#39;d much rather do my work in a GUI. Nicer fonts, actual copy-paste handling.&lt;/p&gt;

&lt;p&gt;But, OpenCode had a lot more flexibility. I&#39;m a Windows user, but I also do my day job work in WSL. I found a third-party OpenCode web UI called CodeNomad. Figured out I could run the CodeNomad + OpenCode processes inside of WSL, load up the web UI on the Windows side, and not deal with cross-platform filesystem issues.&lt;/p&gt;

&lt;p&gt;I&#39;d bookmarked hundreds of potentially useful AI tools, techniques, approaches. I scoured the list, found several tools that looked like a good fit. I used OpenCode + Claude (henceforth OCC) to start customizing my own OpenCode config. I had it cross-compare plugins and tools. I started generating my own OpenCode plugins to fit my needs. I customized the &lt;code&gt;AGENTS.md&lt;/code&gt; and skill files. I generated custom scripts to deterministically handle parts of my workflow and eliminate steps the agent would have had to do via tool calls.&lt;/p&gt;

&lt;p&gt;By the end of the break, I had a fully loaded new OCC setup, ready to work the way &lt;em&gt;I&lt;/em&gt; wanted to work.&lt;/p&gt;

&lt;h3 id=&#34;the-re-pivot&#34;&gt;The Re-Pivot&lt;/h3&gt;

&lt;p&gt;In late January, Replay re-found our direction.&lt;/p&gt;

&lt;p&gt;We put together &lt;a href=&#34;https://docs.replay.io/basics/replay-mcp/overview&#34;&gt;Replay MCP&lt;/a&gt;, allowing agents to do the hard work of investigating a Replay recording. I identified some existing pieces of infrastructure we&#39;d previously built that we could tie together to form a new product line for automatically debugging failed E2E tests, and that this was a highly promising business direction for us to focus on.&lt;/p&gt;

&lt;p&gt;We went all in.&lt;/p&gt;

&lt;p&gt;Time travel debugging was always the promise, the potential, the future. We&#39;d struggled to sell the vision and the use case, and ran into friction with humans trying to adopt the tools. Now, with agentic development 100Xing PR rates, Replay could fit into the automated QA story in ways no other tool could solve. And, Replay MCP gives agents the same time travel superpowers that humans always had with the Replay DevTools UI.&lt;/p&gt;

&lt;p&gt;So now I&#39;ve got an agent workflow, a product direction, and a license to go build Awesome Time Travel Superpowers again. This is going to change the world and fulfill the vision.&lt;/p&gt;

&lt;p&gt;Let&#39;s &lt;em&gt;rock&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&#34;part-7-warp-speed&#34;&gt;Part 7: Warp Speed&lt;/h2&gt;

&lt;h3 id=&#34;pulling-it-all-together&#34;&gt;Pulling It All Together&lt;/h3&gt;

&lt;p&gt;A few days later, I had an incredible brainstorm.&lt;/p&gt;

&lt;p&gt;In summer 2023, I&#39;d played with a Replay time-travel-based perf analysis tool for React and Redux. There are tools out there to capture React perf, but they&#39;re limited. They mostly only work against dev React builds, the numbers are only useful in relative terms (&amp;quot;CompA is 3x as slow as CompB&amp;quot;), and they don&#39;t tell you anything about how Redux dispatches fit into the render. There&#39;s nothing out there that can break down a dispatch into separate times for reducer, subscriber callbacks, selectors, and ensuing React render time.&lt;/p&gt;

&lt;p&gt;I had whipped up a hacky POC to extract those perf numbers, by digging into the guts of React and instrumenting key points in React itself, and similarly in Redux. It worked! But it was too slow. Took way too long to collect the data. Wasn&#39;t a priority, so we never shipped it or pushed it forward.&lt;/p&gt;

&lt;p&gt;We spent 2024-25 building out a sophisticated React analysis layer, so that we could create an async dependency graph: &amp;quot;DOM update caused by React render caused by setState caused by promise resolve caused by network request caused by useEffect&amp;quot;, etc. I&#39;d done much of that analysis work.&lt;/p&gt;

&lt;p&gt;I suddenly realized that the analysis layer we&#39;d built &lt;em&gt;was&lt;/em&gt; the system I&#39;d tried to build a few years earlier! Or rather, it was a vastly better implementation of the data extraction, and it covered &lt;em&gt;React&lt;/em&gt;. Now all I had to do was repeat the same instrumentation patterns for Redux, and I could recreate the same perf analysis insights!&lt;/p&gt;

&lt;p&gt;So I did! Had my agent read up on the React instrumentation approach, identify the key lines in Redux, look at my previous POC, and crank out the implementation. Bam. And within a couple days, I had the Redux + React perf insights coming together. Even better, I could extract those perf insights from &lt;em&gt;production React apps&lt;/em&gt;, something no other tool could do!&lt;/p&gt;

&lt;p&gt;I went kinda crazy with this newfound power :) I started generating a bunch of React and Redux insight reports, trying to see what I could pull together with the data we had available.&lt;/p&gt;

&lt;h3 id=&#34;pattern-matching&#34;&gt;Pattern Matching&lt;/h3&gt;

&lt;p&gt;I&#39;d spent most of Fall 2024 and Spring 2025 working on that analysis layer. It was painstaking work.&lt;/p&gt;

&lt;p&gt;A former Replay teammate had insisted there was no possible way we could actually instrument the guts of React. It would be impossible to maintain it. React changed too much over time. We&#39;d be eternally trying to keep up with the React team.&lt;/p&gt;

&lt;p&gt;He was right.&lt;/p&gt;

&lt;p&gt;I made it work anyway :)&lt;/p&gt;

&lt;p&gt;The original version had looked for specific source fragments in the one experimental React build from Feb 2024 that we happened to be using in our own DevTools codebase. To make it work with React 18, I&#39;d had to spend weeks carefully looking through different ReactDOM dev and prod artifacts to find the equivalent methods and copy the exact fragments from React 18 so our analysis layer could insert the right callbacks. Then I had to do the same thing for React 19, and that was a &lt;em&gt;massive&lt;/em&gt; headache due to the drastic internal changes in React&#39;s implementation between 18 and 19. Functions had been moved, renamed, migrated. The Closure Compiler had inlined some functions that we cared about.&lt;/p&gt;

&lt;p&gt;My first couple passes at this were intentionally ugly and unmaintainable. I didn&#39;t care about how the code was organized. I just needed it to &lt;em&gt;work&lt;/em&gt;. Once I verified the output, &lt;em&gt;then&lt;/em&gt; I could look for the right abstractions and common patterns, and try to organize that logic properly.&lt;/p&gt;

&lt;p&gt;Our instrumentation layer looks for 40+ unique locations in the React bundle. &lt;code&gt;createElement&lt;/code&gt;, &lt;code&gt;renderWithHooks&lt;/code&gt;, effect creation and execution, and many more. I settled on a factory function pattern. Every single location that we cared about, I created a factory function that accepted a &lt;code&gt;reactVersion&lt;/code&gt; object with details on the major and minor version, dev or prod or experimental, and other distinguishing factors. Then I wrote simple &lt;code&gt;if/else&lt;/code&gt; logic based on the versions to decide which fragments and variables and snippets we cared about that for that version.&lt;/p&gt;

&lt;p&gt;It was ugly. It was verbose.&lt;/p&gt;

&lt;p&gt;It was &lt;em&gt;straightforward&lt;/em&gt;. It encapsulated the complexity.&lt;/p&gt;

&lt;p&gt;It &lt;em&gt;worked&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I later went through and hardened it. I replaced literal copy-pasted source code strings with &lt;code&gt;ast-grep&lt;/code&gt; pattern matching, to ignore whitespace and garbage compiler output variable names and focus on the &lt;em&gt;structure&lt;/em&gt; of the code.&lt;/p&gt;

&lt;p&gt;That sucked up &lt;em&gt;months&lt;/em&gt; in 2024-25. We didn&#39;t even care about React 19 at the time - our app builder specifically used React 18. But React 19 had just come out. And if we ever &lt;em&gt;were&lt;/em&gt; going to make this a production reality in the future, I knew it would &lt;em&gt;have&lt;/em&gt; to handle React 19, and who knows when the React team might start shipping 19.x minors. So better to take the time to do that &lt;em&gt;now&lt;/em&gt;. Really only looked for React artifacts as they&#39;d appear in a simple SPA like Vite, intentionally &lt;em&gt;didn&#39;t&lt;/em&gt; handle Next.js and complexity like the App vs Pages Router or canary builds. But I felt confident I&#39;d put the right foundation in place.&lt;/p&gt;

&lt;p&gt;Fast-forward to Feb 2026. I&#39;m back in the analysis layer. Suddenly we&#39;re trying to analyze recordings that aren&#39;t just our own app builder, but real apps in the wild. Next.js 14/15/16, Webpack/Turbopack, some other weird experimental React 19+++ builds with feature flags turned on.&lt;/p&gt;

&lt;p&gt;And I &lt;em&gt;already had the right architecture and patterns and encapsulation in place&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It was &lt;em&gt;dumb&lt;/em&gt; code. &lt;em&gt;ugly&lt;/em&gt; code. &lt;em&gt;Predictable&lt;/em&gt; code.&lt;/p&gt;

&lt;p&gt;And you know what &lt;em&gt;looooooves&lt;/em&gt; dumb, predictable, &lt;em&gt;repetitive&lt;/em&gt; code?&lt;/p&gt;

&lt;p&gt;LLMs :)&lt;/p&gt;

&lt;p&gt;For the first time, I tried telling my agent about the React instrumentation layer and what we needed to add to expand it for these cases. It read the React fragment files and the rest of the instrumentation layer. It slurped up the various ReactDOM bundles I&#39;d collected. And so help me it started comparing 19.0 and 19.1 and 19.2 and Next 19.random.canary and whatever other weird versions I was looking at, and within a few minutes it could tell me where the relevant functions and fragments had migrated between versions and how they&#39;d changed and what we needed to update in the fragment factories to handle those.&lt;/p&gt;

&lt;p&gt;I think I actually literally screamed at one point?&lt;/p&gt;

&lt;p&gt;I mean, I spent &lt;em&gt;months&lt;/em&gt; on this! I was so deep in the weeds and trying to understand what each fragment meant and why it mattered and how our analysis layer turned these points into a graph and what the actual variables were and how to insert the callbacks correctly without breaking the instrumented bundle.&lt;/p&gt;

&lt;p&gt;And now I just say &amp;quot;here&#39;s the pattern and the current task, go figure out the next changes we need to add&amp;quot;, and it just... &lt;em&gt;does it&lt;/em&gt;? Correctly? &lt;em&gt;Faster than I could have done&lt;/em&gt;?!?!?!? ARE YOU &lt;em&gt;KIDDING ME&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;But here&#39;s the thing. An LLM could never have come up with this from scratch. Even if I were rebuilding this from nothing today, &lt;em&gt;I&lt;/em&gt; would have to tell it what I wanted it to accomplish. Even if it came up with the methods, &lt;em&gt;I&lt;/em&gt; would have to provide the intent.&lt;/p&gt;

&lt;p&gt;Looking back, I am &lt;em&gt;so proud&lt;/em&gt; of 2025-me. I was upset, and angsting, and confused. But I still took the time to understand, to investigate. I built the right foundation, the hard way. I built the mental model in my head, I got the fragments working, I decided on the factory function encapsulations and the &lt;code&gt;ast-grep&lt;/code&gt; usage and the file structures.&lt;/p&gt;

&lt;p&gt;Because &lt;em&gt;I&lt;/em&gt; did the hard work the first time, it paid off in 2026. When we needed to update that analysis layer for React 19.x, and handle Next.js variations and React canaries, the foundation was in place. I just had to build on top of it. A couple weeks of expansion, instead of months of building from scratch.&lt;/p&gt;

&lt;p&gt;And with the foundation and those patterns were in place, &lt;em&gt;now&lt;/em&gt; I could just point my agent at it and say &amp;quot;here&#39;s the right patterns, here&#39;s the goal, here&#39;s what we&#39;re adding. Read, learn, compare, &lt;em&gt;do it&lt;/em&gt;&amp;quot;.&lt;/p&gt;

&lt;h3 id=&#34;shipping-for-agents&#34;&gt;Shipping for Agents&lt;/h3&gt;

&lt;p&gt;The &lt;a href=&#34;https://docs.replay.io/basics/replay-devtools/overview&#34;&gt;Replay DevTools UI&lt;/a&gt; had started as a fork of the Firefox DevTools. We&#39;d added time travel abilities, and rewritten the whole codebase in the process. That let me as a human investigate Replay recordings and do time-travel debugging, with my own eyes and knowledge.&lt;/p&gt;

&lt;p&gt;Now, we had an MCP. That meant &lt;em&gt;agents&lt;/em&gt; were doing the hard work. And they don&#39;t get tired :) Confused, maybe. Still very easily misled. But they&#39;ll happily just keep going indefinitely.&lt;/p&gt;

&lt;p&gt;I had a few specific examples I was using as personal benchmarks. In one case, I&#39;d pushed a PR to update the Replay DevTools UI to React 19. When I pushed the branch, half our Playwright E2E tests failed. Usually means you broke something badly. We already had our own repo set up to do Replay recordings of all tests, so I just popped open one failing test recording. Scrolled down the list of console messages, and sure enough, last message was an error: &lt;code&gt;findDOMNode is not a function&lt;/code&gt;, from React Transition Group. Yup, sure, need to bump that too or tweak usage. 30s, done.&lt;/p&gt;

&lt;p&gt;But could an &lt;em&gt;agent&lt;/em&gt; find the answer that fast?&lt;/p&gt;

&lt;p&gt;I tried feeding the recording to an agent, and it bumbled around for 10-15min. Didn&#39;t help the &lt;code&gt;ConsoleMessages&lt;/code&gt; tool was broken and didn&#39;t report the error :) Eventually I &amp;quot;suggested&amp;quot; it use the &lt;code&gt;Screenshot&lt;/code&gt; tool. It saw the error overlay, dove into the root error boundary component, added a logpoint, exfiltrated the error, got the right result.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I&lt;/em&gt; found the answer in the recording in 30s. Could I give an &lt;em&gt;agent&lt;/em&gt; that ability?&lt;/p&gt;

&lt;p&gt;So I started rewriting and expanding all our Replay MCP tools. I built a &lt;code&gt;RecordingOverview&lt;/code&gt; tool that surfaced React version, Playwright test results and errors, console or React error boundary errors, React renders, Redux / Zustand / TanStack Query state results, network requests. I built a &lt;code&gt;ReactRenders&lt;/code&gt; tool that lets an agent drill down into render details. A &lt;code&gt;ReduxActions&lt;/code&gt; tool that provides drill down into Redux actions and state, and similar tools for Zustand and TanStack Query.&lt;/p&gt;

&lt;p&gt;By the time I was done, I did see my agent find that same bug in &amp;lt;1min.&lt;/p&gt;

&lt;p&gt;I also tried recreating other cases, like a React bug that Dan Abramov had reported, and my agent found that same bug in &amp;lt;10 min (faster or shorter depending on prompt quality).&lt;/p&gt;

&lt;p&gt;Guess what. Turns out that surfacing deterministic info deterministically and providing more details and the ability to drill down and dive deep, helps people &lt;em&gt;and&lt;/em&gt; agents. And now that I had all this time-travel info at my fingertips, I can build the tools that make solving impossible problems possible.&lt;/p&gt;

&lt;p&gt;So apparently now I&#39;m back to building UI. But for agents more than humans.&lt;/p&gt;

&lt;h2 id=&#34;part-8-so-what-do-i-think-today-anyway&#34;&gt;Part 8: So What Do I Think Today, Anyway?&lt;/h2&gt;

&lt;p&gt;So that&#39;s my story as of today.&lt;/p&gt;

&lt;p&gt;If you&#39;ve gotten this far, congratulations. Thanks for sticking with me. It&#39;s a lot of words (even for me!), and a lot of personal details. I know. And there&#39;s more to go.&lt;/p&gt;

&lt;p&gt;So what do &lt;em&gt;I&lt;/em&gt; think about all this? About agents, and using AI to write code? All the fears and concerns that I wrote about so vividly earlier?&lt;/p&gt;

&lt;p&gt;Well, I do have opinions and thoughts. &lt;em&gt;You&lt;/em&gt; didn&#39;t ask, probably. But some people have. And it&#39;s my blog, and I&#39;m writing this one for me. And as always I hope &lt;em&gt;some&lt;/em&gt; people get value out of this. So slap an MIT license on these thoughts - up for grabs, do what you want with this, not implied for any particular use, not my fault if this doesn&#39;t work for you.&lt;/p&gt;

&lt;h3 id=&#34;most-of-my-fears-are-still-valid-and-so-are-you&#34;&gt;Most Of My Fears Are Still Valid, And So Are You&lt;/h3&gt;

&lt;p&gt;I wrote a whole laundry list of fears up top.&lt;/p&gt;

&lt;p&gt;Some of them turned out to be non-factors.&lt;/p&gt;

&lt;p&gt;I thought I would essentially erase my existence if I ever stooped to asking an AI to write code for me. Well, I did it. I&#39;m still here. I&#39;m still me. So I was wrong on that one.&lt;/p&gt;

&lt;p&gt;I thought I&#39;d utterly hate being a &amp;quot;pseudo-PM/code reviewer&amp;quot; all the time. Uh. Well. Guess what. I&#39;m kinda mostly a pseudo-PM/code reviewer. And it... doesn&#39;t suck? We&#39;ll get back to that in a minute.&lt;/p&gt;

&lt;p&gt;Clearly the generated code quality is &lt;em&gt;better&lt;/em&gt; than it used to be. Not necessarily great! It&#39;s not elegant. AI will happily keep slapping on more layers, not extracting abstractions. But we&#39;re long past the hallucination stage.&lt;/p&gt;

&lt;p&gt;But most of the rest of my fears and concerns are still there. Especially the larger societal ones.&lt;/p&gt;

&lt;p&gt;I know, I know. Every generation worries about &amp;quot;The Kids These Days&amp;quot;. There&#39;s quotes from ancient Rome about how the kids are lazy and don&#39;t do anything. We&#39;ve survived the last few thousand years. Society&#39;s still here. Human condition.&lt;/p&gt;

&lt;p&gt;I do seriously worry about the large-scale impacts of AI on our collective thinking processes. It was hard enough to teach critical thinking skills in school when we had to do the work ourselves. We relied on artifacts like essays and projects as both forcing functions to make people learn the material, and social proof that they &lt;em&gt;had&lt;/em&gt; learned the material and done the work. Now that anyone can copy-paste an assignment into their LLM of choice and paste the results back into a grading system in about 30s, there&#39;s no need to do the learning or thinking, and the artifact is no longer proof of the learning and the work. What happens to our world in the next 20-30 years, when we&#39;ve Wall-e style obliterated our ability to think or learn or do?&lt;/p&gt;

&lt;p&gt;We rely on photographs and voice recordings and trust that these things are proof that something actually happened. We&#39;ve already seen those can be mimicked and forged instantly. How can we trust any news source or report or proof, and verify that things actually happened as described?&lt;/p&gt;

&lt;p&gt;I&#39;m towards the tail end of my career. I already felt out of touch with what today&#39;s junior devs must be going through. My own career arc has been unique - no one could replicate the specific opportunities I had at the times I had them. I have no idea what it&#39;s like to have to grind l33tcode or algos/DSAs, or go through a bootcamp and try to stand out amongst a sea of otherwise identical FE devs with no experience. What happens to people trying to get into the industry? What does their pathway look like? How do they build a career, gain experience?&lt;/p&gt;

&lt;p&gt;I have no answers. Not that anyone would care if I did anyway :) I worry for the future in a lot of ways. But it&#39;s not mine to build.&lt;/p&gt;

&lt;p&gt;I&#39;ve talked to plenty of people who still refuse to use LLMs in any way shape or form. Who fear for the future of the industry, mourn the loss of their craft.&lt;/p&gt;

&lt;p&gt;I understand. I agree. I was there. I&#39;m &lt;em&gt;still&lt;/em&gt; there. Please don&#39;t take my own change of heart and current excitement as any kind of statement that your own feelings are wrong. You are entirely justified to feel that way, because Feelings Are Valid and Real. I hope you can find mental peace and safety in the midst of this insanity.&lt;/p&gt;

&lt;h3 id=&#34;the-tiger-is-out&#34;&gt;The Tiger Is Out&lt;/h3&gt;

&lt;p&gt;There&#39;s a beautiful little poem apparently written by a 6yo kid a few years ago:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The tiger&lt;br /&gt;
He destroyed his cage&lt;br /&gt;
Yes&lt;br /&gt;
YES&lt;br /&gt;
The tiger is out&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, guess what. The LLM is out. And it&#39;s not going away.&lt;/p&gt;

&lt;p&gt;I&#39;ve read a lot of the &amp;quot;THEY CAN&#39;T &lt;em&gt;POSSIBLY&lt;/em&gt; KEEP GETTING AWAY WITH THIS! IT&#39;S A HOUSE OF CARDS! FINANCIAL RACKETEERING! CIRCULAR MONEY LAUNDERING! UNSUSTAINABLE PACE OF GROWTH! FAKE DEALS! NONE OF THESE DATA CENTERS ACTUALLY EXIST!&amp;quot; articles. I think there&#39;s a lot of truth to all that! It&#39;s entirely possible that a few years from now the entire AI ecosystem could collapse because of financial shenanigans, and that it could take down the US and world economies with them.&lt;/p&gt;

&lt;p&gt;But LLMs as a technology exist. The genie is out of the bottle. Pandora&#39;s box is open. Pick your metaphor here.&lt;/p&gt;

&lt;p&gt;And even if we stopped development on LLM model tech &lt;em&gt;right this second&lt;/em&gt;, and we never had a single improvement in quality or memory usage or token speed for the rest of time... what we have &lt;em&gt;now&lt;/em&gt; is already enough to upend many aspects of society as we&#39;ve known it.&lt;/p&gt;

&lt;p&gt;There will be positives from this! I&#39;m not sitting here saying anything involving LLMs is inherently bad. Remember, I&#39;m actually quite happy having LLMs crank out code for me at this point. I&#39;ve talked to friends who are seeing potential medical benefits, and there&#39;s a lot more.&lt;/p&gt;

&lt;p&gt;But I do mean that we have unleashed a technology that will continue to change our society in ways we can and can&#39;t predict going forward. Just the predictions I &lt;em&gt;can&lt;/em&gt; see are concerning, and I&#39;ve got a pretty limited imagination.&lt;/p&gt;

&lt;p&gt;I don&#39;t know what the reality is on any of the ecological aspects (power and water usage). No idea on the big ethical / moral &amp;quot;WHERE DID THEY GET ALL THE TRAINING DATA? CAN ANY OUTPUT FROM AN LLM BE VALID WHEN IT&#39;S ALL JUST COPYRIGHTED INPUT?&amp;quot; questions. And to be frank at this point it&#39;s kind of irrelevant.&lt;/p&gt;

&lt;p&gt;Is this the future I &lt;em&gt;want&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;No, not particularly.&lt;/p&gt;

&lt;p&gt;Do I think everyone should jump wholeheartedly into AI and use it everywhere for everything? Of course not and I hope you see that distinction in my explanations here.&lt;/p&gt;

&lt;p&gt;What does this mean &lt;em&gt;outside&lt;/em&gt; the software engineering industry? I have &lt;em&gt;no idea&lt;/em&gt;. I see lots of discussion on AI eating writing and art and music. That seems wrong, in a different way. I dislike AI writing tone, and I detect written slop a mile away, and yet I&#39;ve also used AI to generate summaries of text for myself and for work because there&#39;s still &lt;em&gt;some&lt;/em&gt; value in the content as ugly as it is.&lt;/p&gt;

&lt;p&gt;I suspect LLMs do better at code than in other domains, but I have no experience or knowledge what LLM use looks like in law or physics or finance. Wouldn&#39;t surprise me if there&#39;s a big difference in results, but man, I can&#39;t even keep up with &lt;em&gt;our&lt;/em&gt; industry or even just the React ecosystem, don&#39;t ask me to keep up with other industries too :)&lt;/p&gt;

&lt;p&gt;As you&#39;ve seen, I &lt;em&gt;am&lt;/em&gt; excited about what I personally can do with AI. I also see every day that it&#39;s causing problems directly and indirectly. So, no, I&#39;m not blind to the damage that AI is doing, and that&#39;s the aspects that concern me. But given that it exists, now the question becomes how I&#39;m going to react and use this myself, same as every other technology that has come out in my lifetime.&lt;/p&gt;

&lt;p&gt;I&#39;m a firm believer in dealing with reality the way it is. Not the way I &lt;em&gt;want&lt;/em&gt; it to be. Sure, I&#39;ll gripe and complain and push if something isn&#39;t the way I want. I don&#39;t blindly accept it or act like things &lt;em&gt;can&#39;t&lt;/em&gt; change.&lt;/p&gt;

&lt;p&gt;But you&#39;ve got to deal with the world as it actually exists. Good, bad, and ugly. And in this case, LLM tech exists, and it&#39;s already this powerful, and this easy to use. It&#39;s now part of our reality. Acknowledge that fact, and plan accordingly.&lt;/p&gt;

&lt;h3 id=&#34;gotta-go-fast&#34;&gt;Gotta Go Fast&lt;/h3&gt;

&lt;p&gt;For software engineering especially: we built our processes around &lt;em&gt;people&lt;/em&gt;. The Agile Manifesto, Scrum, standups, PR reviews, issue trackers, Git commit messages. It took time to plan. Writing code was expensive and time-consuming. We had to make sure we were writing the correct code in the first place. Can&#39;t waste time on irrelevant experiments.&lt;/p&gt;

&lt;p&gt;AI broke that constraint.&lt;/p&gt;

&lt;p&gt;With AI, we can crank out infinite amounts of code, essentially for free, and essentially immediately.&lt;/p&gt;

&lt;p&gt;None of our processes were designed for that.&lt;/p&gt;

&lt;p&gt;I spent a lot of time at AI Engineer and React Miami in April. I had dozens of conversations. And a lot of them were different forms of the same question: &amp;quot;how do we scale our review / test / QA / deploy / planning processes to keep up with the amount of code we&#39;re generating?&amp;quot;.&lt;/p&gt;

&lt;p&gt;I have a &lt;em&gt;sort of&lt;/em&gt; answer to that. And a lot of you aren&#39;t going to like it :)&lt;/p&gt;

&lt;p&gt;On the one hand, having an infinite codegen at your fingertips &lt;em&gt;does&lt;/em&gt; change our processes for how we do things. Why make a napkin-styled wireframe of a UI to sketch out the layout, when you can just prompt it into existence in 30s? Why waste a couple weeks on building one prototype, when you can crank out 10 prototypes simultaneously and compare the results? Why spend time going back and forth with handoffs between designers in Figma and ensuring a dev has the right design tokens in place, when you can just have them both landing updates at the same time? This is legitimately possible, and does actually change so many of our assumptions for building apps.&lt;/p&gt;

&lt;p&gt;But as my mother told us all the time growing up: &amp;quot;humans will take everything to the extreme&amp;quot;.&lt;/p&gt;

&lt;p&gt;Many of us have already experienced or seen AI psychosis. When you start writing code with &lt;em&gt;one&lt;/em&gt; agent, it can edit files faster than you can. We&#39;re programmers - we already know that computers can execute our desires faster than we can do them manually. Write one line of code. Put it in a loop, it runs many times, automatically. Throw in a thread pool, now they&#39;re in parallel. Distribute the system. Scale. GPUs. Cores. Optimize.&lt;/p&gt;

&lt;p&gt;Okay, what happens if I run &lt;em&gt;two&lt;/em&gt; agent sessions at once? Can I ping-pong between tabs? It takes a couple minutes for Agent 1 to do its work, surely I can switch and tell Agent 2 to do some work in the meantime. It&#39;s the XKCD &amp;quot;COMPILING!&amp;quot;, except now instead of sword fights in the hallway, we&#39;re just task switching. Context switching. Having to keep multiple tasks in our brain at once.&lt;/p&gt;

&lt;p&gt;Over the years I&#39;ve found that social media already ruined my ability to focus. I used to be able to intently focus on a single task for hours. Now I kick off a command that takes 30s, and my brain wants to go check Twitter and Bluesky and Reddit and HN just in case there were any new posts in the last 5 minutes. It&#39;s &lt;em&gt;bad&lt;/em&gt;. I hate it.&lt;/p&gt;

&lt;p&gt;Well, guess what. Running 2-3 agent sessions at once is just as bad. And that&#39;s just the starting point.&lt;/p&gt;

&lt;p&gt;Okay, if we can run a couple sessions at once, but we&#39;re &amp;quot;manually&amp;quot; driving our agents... what happens if we remove the brakes? Why should I have to tell the agent what to do, or approve the permissions checks? SCALE THE SYSTEM BABY! YOLO MODE FOR LIFE! Why not run 5 agents? 10 agents? 100? 1000? Build a custom multi-pane dashboard just to track all my agents. Don&#39;t need to know what they&#39;re doing or how, just that they&#39;re all busy at the same time and not blocking the merge queue. Markdown&#39;s outdated, too many markdown files. Throw some gas rigs and mayors and polecats in there. We&#39;re tokenmaxxing, there&#39;s a leaderboard, burn more tokens or you&#39;re fired. Build a dark factory. No human ever looks at the code. It&#39;s Steve Ballmer&#39;s &amp;quot;DEVELOPERS! DEVELOPERS! DEVELOPERS!&amp;quot;, except now it&#39;s &amp;quot;AGENTS! AGENTS! AGENTS!&amp;quot;&lt;/p&gt;

&lt;p&gt;The goal is unlimited speed.&lt;/p&gt;

&lt;p&gt;And what happens when you go too fast?&lt;/p&gt;

&lt;p&gt;You crash.&lt;/p&gt;

&lt;h3 id=&#34;oops-it-s-capitalism&#34;&gt;Oops It&#39;s Capitalism&lt;/h3&gt;

&lt;p&gt;This is a pretty ironic section for me to write. I come from a conservative background. My own views and opinions have evolved significantly over time, but I&#39;m hardly what you&#39;d call an activist.&lt;/p&gt;

&lt;p&gt;So here&#39;s my late-night, actual, no-kidding opinion:&lt;/p&gt;

&lt;p&gt;We, as an industry, need to collectively accept that &lt;strong&gt;humans and processes and even agents &lt;em&gt;have limits&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And sooner or later we&#39;re &lt;em&gt;all&lt;/em&gt; going to have to take a step back and figure out what our safe, reasonable, and &lt;em&gt;maintainable&lt;/em&gt; limits are. Because we&#39;re all about to learn those lessons the hard way.&lt;/p&gt;

&lt;p&gt;They&#39;ll vary by company and team. Some teams will set up better automated processes. Maybe we&#39;ll democratize it, whatever the QA / CI version of k8s is so that we can all benefit from auto-scaling systems. But &lt;em&gt;there will fundamentally be limits to how fast we can build and ship code&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Maybe it&#39;s 3x current / historical speed. Maybe it&#39;s 10x. I dunno.&lt;/p&gt;

&lt;p&gt;But right now it seems like &lt;strong&gt;the entire industry is assuming there &lt;em&gt;isn&#39;t&lt;/em&gt; a limit. And that if it &lt;em&gt;is&lt;/em&gt; possible to go faster, then we &lt;em&gt;must&lt;/em&gt; go faster.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everyone&#39;s scared of how fast everyone else might go. Everyone&#39;s jumping on AI to get ahead of the curve, to try to beat their competition to the punch. Can&#39;t just naturally let adoption happen, have to mandate it top-down. Slap those sparkle icons in every single toolbar and panel, shove those &amp;quot;NOW WITH AI&amp;quot; features down everyone&#39;s throats whether they like it or not.&lt;/p&gt;

&lt;p&gt;Wait, why are we going faster? To ship features? To beat our competitors to market? To deliver shareholder value?&lt;/p&gt;

&lt;p&gt;Oops. It&#39;s Capitalism.&lt;/p&gt;

&lt;p&gt;Don&#39;t get me wrong. I&#39;m the last person who should be delivering a critique of our economic system here :) But as someone who&#39;s read too many online rants... well, that seems to be the final answer for all of this. We Go Faster so that we can Deliver Value in service of the System.&lt;/p&gt;

&lt;p&gt;This is not sustainable.&lt;/p&gt;

&lt;h3 id=&#34;maintainability-is-the-mindset&#34;&gt;Maintainability is the Mindset&lt;/h3&gt;

&lt;p&gt;I personally learned years ago that even in a great job, with a comfortable pace of work, and managers who actually care about you as a person, and tasks that I personally find fascinating and interesting and challenging... &lt;strong&gt;you still have to set boundaries&lt;/strong&gt;. There&#39;s always more work to do. Always another fire to fight, another bug to fix, another feature to get out the door. No one else is going to tell you &amp;quot;you&#39;ve done too much work, throttle back&amp;quot;. You have to enforce that yourself.&lt;/p&gt;

&lt;p&gt;It can wait.&lt;/p&gt;

&lt;p&gt;I love work. I love being productive. I view the world in terms of checkboxes and getting things done, which I&#39;m very well aware is not the healthiest mindset and trust me my therapist knows all about this trait :)&lt;/p&gt;

&lt;p&gt;But &amp;quot;go faster, at all costs&amp;quot;, should not be the goal.&lt;/p&gt;

&lt;p&gt;Michelle Bakels has given an amazing talk on developer health, and one of the key lines was how &lt;strong&gt;&amp;quot;rest isn&#39;t &lt;em&gt;earned&lt;/em&gt;. It&#39;s a critical part of performing at our best.&amp;quot;&lt;/strong&gt; Everyone should watch that and take that mindset to heart.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal should be a healthy, consistent, &lt;em&gt;sustainable&lt;/em&gt;, &lt;em&gt;maintainable&lt;/em&gt; pace of development and shipping&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;m not the world&#39;s best poster child for this. I push myself hard, always feeling like I &lt;em&gt;could&lt;/em&gt; and &lt;em&gt;ought&lt;/em&gt; to be doing more than I am. I&#39;m trying :) Work in progress. Do as I say, not always as I do myself.&lt;/p&gt;

&lt;p&gt;Maybe that&#39;s 10x for you, and 3x for me. Whatever. That&#39;s fine.&lt;/p&gt;

&lt;p&gt;But the sooner we all intentionally acknowledge that and adjust our plans and expectations accordingly, the better.&lt;/p&gt;

&lt;h3 id=&#34;but-non-determinism&#34;&gt;But Non-Determinism?&lt;/h3&gt;

&lt;p&gt;I wrote so much at the start of this post about how bad non-determinism is. I &lt;em&gt;want&lt;/em&gt; predictability. I &lt;em&gt;want&lt;/em&gt; to re-run my code and know that it&#39;s going to execute the same way every time given the same inputs. It&#39;s literally the core of how Replay time-travel works.&lt;/p&gt;

&lt;p&gt;I&#39;ve seen folks online hammer on this point. LLMs are inherently non-deterministic. How can you possibly rely on that? Forget even hallucinations, how can you build apps when you can&#39;t guarantee what the output is?&lt;/p&gt;

&lt;p&gt;I&#39;ve also read comparisons to how this is all just virtual slot machines and gambling. In the same way that social media gives us dopamine hits - &amp;quot;ooh look, 3 new posts since I last refreshed, maybe one of these will be interesting!&amp;quot; Gimme something new, something different, &lt;em&gt;maybe&lt;/em&gt; it&#39;s useful. Same thing with LLMs and code. Give it instructions, pull the lever, watch the &lt;del&gt;dials spin&lt;/del&gt; messages and diffs, and then inspect the results and &lt;em&gt;hope&lt;/em&gt; it does what you want.&lt;/p&gt;

&lt;p&gt;There&#39;s a lot of truth to it. I feel it all the time.&lt;/p&gt;

&lt;p&gt;But we&#39;ve always built guardrails and tools to keep the work on track. We use code formatters to make the code style consistent and eliminate the arguments over tabs vs spaces. We write unit and integration and E2E tests to verify the whole system works as intended. We typecheck and lint and squiggle-ify in our editors and in CI.&lt;/p&gt;

&lt;p&gt;Non-determinism &lt;em&gt;can&lt;/em&gt; be made &lt;em&gt;sufficiently&lt;/em&gt; deterministic.&lt;/p&gt;

&lt;p&gt;It takes work. It&#39;s a different &lt;em&gt;kind&lt;/em&gt; of work. The results aren&#39;t always what you want. But with enough boundaries in place, the non-deterministic output &lt;em&gt;should&lt;/em&gt; be close enough to fulfill the intended goal, and can be tweaked if needed. Provide the right context, the right prompts, the right skill files. Don&#39;t cut an agent loose autonomously, review the plan and make sure it&#39;s actually what &lt;em&gt;you&lt;/em&gt; want done. Agents love to type-check. Give them the lint errors, enforce the commit rules, throw all the static analysis in there. Add the AI-powered code review, ralph loop it if you have to until the agent and the judge are both happy.&lt;/p&gt;

&lt;p&gt;I still believe in making as much of the system as deterministic as possible. Redux reducers. 100% deterministic codegen. Turn patterns and routines into scripts, encode the knowledge. Minimize how much work the LLM actually has to do. Make it &lt;em&gt;code&lt;/em&gt; anywhere you can. And then you can use an LLM to help with the automation.&lt;/p&gt;

&lt;p&gt;There&#39;s a lot of variation in how people use AI. Agents, harnesses, workflows, models, prompts, plugins, skills. I see some complaints and think &amp;quot;well &lt;em&gt;I&#39;ve&lt;/em&gt; never had that problem myself&amp;quot;, and I don&#39;t know if it is the codebase and domain I&#39;m working in, or the models I&#39;m using, or the prompts and context engineering, or just the whims of the RNG. No guarantees, no promises, this is just me saying what I&#39;ve found works for me.&lt;/p&gt;

&lt;h3 id=&#34;is-this-actually-better&#34;&gt;Is This Actually &lt;em&gt;Better&lt;/em&gt;?&lt;/h3&gt;

&lt;p&gt;.... maybe? Sort of? Partly?&lt;/p&gt;

&lt;p&gt;I&#39;ve seen people throw around stats for how actually writing code is only N% of the work we do, and so even if AI writes code 3-5x faster, it&#39;s only a partial speedup. Lot of truth to that.&lt;/p&gt;

&lt;p&gt;We&#39;re still pretty early in the adoption/hype curve. At some point you have to actually &lt;em&gt;maintain&lt;/em&gt; codebases that were built with The New Shiny Toy, and then we all realize the horrible mistakes we made during the early hype period. Redux is a classic example of that :) During 2015-2016, people put Redux in &lt;em&gt;sooo many places it should never have been used&lt;/em&gt; (hello controlled forms!), and then by 2017 there was a collective &amp;quot;Oops What Have We Done To Ourselves&amp;quot;.&lt;/p&gt;

&lt;p&gt;My own perspective is limited here. I&#39;ve at least used AI to work on a decent variety of codebases at this point: Replay&#39;s backend and frontend, Redux libraries, some one-off side projects, a couple larger side projects. I&#39;ve found value in all of them. But it&#39;s also only been ~6 months for me, maybe a year for most of us. We&#39;re just seeing the start of the ripple effects.&lt;/p&gt;

&lt;p&gt;I&#39;ve used agents to do a bunch of tasks much faster than I &lt;em&gt;know&lt;/em&gt; I would have done it myself. I&#39;ve seen the agent happily implement individual sub-features I&#39;d had it plan out in a side project, and it wrote each of the files individually matching the listed spec, and &lt;em&gt;none of them got hooked up together at all&lt;/em&gt;, and I didn&#39;t even catch that until it had &amp;quot;finished&amp;quot; all the issues for that feature. I&#39;ve been able to think higher-level, and I&#39;ve had to burn time trying to keep the agent on track. I&#39;ve seen the agent expand my brief thoughts into plans that cover edge cases I never would have considered, and I&#39;ve seen it happily proclaim &amp;quot;clean, no issues&amp;quot; after cranking out a bunch of code and yet missed the blindingly obvious problems.&lt;/p&gt;

&lt;p&gt;But it does seem that &lt;code&gt;while (true) { goodEnough() }&lt;/code&gt; has a value of its own.&lt;/p&gt;

&lt;p&gt;I&#39;ve seen plenty of debates about how AI is going to kill OSS. Maintainers are getting flooded with spammy contributions that look plausible enough. I fully believe that flood is happening. We haven&#39;t had to deal with it as much in the Redux repos, but I&#39;ve certainly seen plenty of examples across the ecosystem. I&#39;ve also seen maintainers say they&#39;re finally working through the issue backlogs and making headway.&lt;/p&gt;

&lt;p&gt;I can tell you it sure feels a lot better &lt;em&gt;mentally&lt;/em&gt; to have found a way to use AI for my work and be happy with the results, than it did when I was spending all my time angsting and fearing for both the industry and my own career. I&#39;m not saying my own mental peace is the only factor to consider here :) but honestly it&#39;s a pretty &lt;em&gt;big&lt;/em&gt; factor personally.&lt;/p&gt;

&lt;p&gt;So I don&#39;t know. I&#39;m using it because I myself have seen evidence it can help me finish my tasks faster and augment my ability to understand code (even if that understanding now takes different forms of effort). I &lt;em&gt;think&lt;/em&gt; that&#39;s a good thing. I see plenty of other people saying similar things. But I fully acknowledge there&#39;s tons of competing pros and cons here, for myself and the industry.&lt;/p&gt;

&lt;h3 id=&#34;what-about-the-craft&#34;&gt;What About the Craft?&lt;/h3&gt;

&lt;p&gt;I talked a lot about the craft of programming earlier. Also kind of ironic. I believed in it, and yet I never felt like my own work ever quite measured up to that ideal. Especially in recent years, I found myself gravitating more towards prototyping, especially with time travel debugging, where my focus was just trying to figure out and prove &amp;quot;is this even &lt;em&gt;possible&lt;/em&gt;?&amp;quot; rather than fully productionize features - and goodness knows &lt;em&gt;that&lt;/em&gt; didn&#39;t involve a lot of &amp;quot;craft&amp;quot; :) (you should see how often &lt;code&gt;// HACK&lt;/code&gt; showed up in parts of my code.)&lt;/p&gt;

&lt;p&gt;So what now? Is there any semblance of a &amp;quot;craft of programming&amp;quot; now that we&#39;re all relying on agents? Soulless Statistical Word Generating Machines, just generating tokens endlessly?&lt;/p&gt;

&lt;p&gt;In some ways, no. That world is gone and it probably isn&#39;t coming back.&lt;/p&gt;

&lt;p&gt;Pick your historical precedent. Cars eliminated horses, etc.&lt;/p&gt;

&lt;p&gt;I talked to a genius-level senior engineer recently. He&#39;s built a reputation as someone who has incredibly deep knowledge and has pulled off some amazing feats. He&#39;s considering leaving the industry soon. He compared it to woodworking. Someone can hand-make a wood table, careful crafting, lots of attention. In some cases, they can command a higher price for a hand-crafted item.&lt;/p&gt;

&lt;p&gt;No one&#39;s going to pay extra just so a human can hand-craft a &lt;code&gt;for&lt;/code&gt; loop.&lt;/p&gt;

&lt;p&gt;This saddens me. I wish it weren&#39;t the case. Please see previous section on Capitalism.&lt;/p&gt;

&lt;p&gt;And yet.&lt;/p&gt;

&lt;p&gt;I personally have found that I am able to use AI tools successfully, &lt;em&gt;because&lt;/em&gt; of my deep experience and knowledge.&lt;/p&gt;

&lt;p&gt;AI has been able to &lt;em&gt;amplify&lt;/em&gt; my intent. It&#39;s a force multiplier. I use it to research portions of a codebase, write up a doc, draw diagrams, help me understand how something works. I feed it several paragraphs of an idea for a feature or a task, it reads a few dozen files and pulls in examples, and it spits out a much more detailed plan that covers a bunch of edge cases I never even would have considered. I modify the plan, I make some adjustments based on my own knowledge, I tell it &amp;quot;implement&amp;quot;, and it cranks out the changes I want far faster than I could have made the edits. I&#39;ve seen drastically different results depending on the quality of the context and the prompt. There is &lt;em&gt;skill&lt;/em&gt; in providing the right context, and yes, &lt;code&gt;SKILL.md&lt;/code&gt; files. It is literally a skill issue :)&lt;/p&gt;

&lt;p&gt;It&#39;s certainly not perfect. Even with today&#39;s models there&#39;s mistakes. But it&#39;s more often mistakes of &lt;em&gt;intent&lt;/em&gt; than syntax or hallucinations.&lt;/p&gt;

&lt;p&gt;And &lt;em&gt;I&#39;m&lt;/em&gt; the one in charge. &lt;em&gt;I&#39;m&lt;/em&gt; driving. I provide the vision, the intent, the directions. And I heavily leverage my expertise to keep the AI on the right track, redirecting when it goes off the rails, asking &amp;quot;wait have we considered this approach?&amp;quot;, insisting that we do things the way &lt;em&gt;I&lt;/em&gt; want.&lt;/p&gt;

&lt;p&gt;I&#39;ve read a bunch of articles lately saying that AI has exposed a split in programmers. There&#39;s people who were in it &lt;em&gt;for the craft itself&lt;/em&gt;, and then there&#39;s people who were in it for the &lt;em&gt;results&lt;/em&gt;, the output, the end product.&lt;/p&gt;

&lt;p&gt;I thought I was in it for both. I got so much joy from saying &amp;quot;this &lt;em&gt;didn&#39;t&lt;/em&gt; exist, and then I thought and I worked, and now it &lt;em&gt;does&lt;/em&gt; exist&amp;quot;. Creation ex nihilo. But also nothing made me happier than those 6-hour uninterrupted deep flow music thumping mind on autopilot deep in the code sessions.&lt;/p&gt;

&lt;p&gt;I still care about the craft. I want to build apps the right way.&lt;/p&gt;

&lt;p&gt;But maybe it was a bit &lt;em&gt;more&lt;/em&gt; about the final result than I thought.&lt;/p&gt;

&lt;p&gt;I really hadn&#39;t worked on any side projects in the last 10 years since I started maintaining Redux. My todo list is perpetually overflowing, there&#39;s always more self-imposed priorities and responsibilities than I can ever get around to. I didn&#39;t have time or brain space or priority to work on code &amp;quot;for fun&amp;quot;. Day job, second unpaid job as maintainer, trying to have a life, can&#39;t fit anything else in there.&lt;/p&gt;

&lt;p&gt;In the last few months I&#39;ve actually whipped up a few side projects! There were ideas that popped into my head. And normally I&#39;d have dismissed them and said &amp;quot;I don&#39;t even have brain space to think about these, much less time to write the code&amp;quot;. But now... if I could spare 30+ minutes to spin it up, I could get an agent session fleshing out a project plan, and then maybe babysit a session while I&#39;m on the couch in the evening. Still &lt;em&gt;some&lt;/em&gt; time and mental overhead, but a far lower barrier to entry than before. So yeah, I actually have built several small projects I never would have even &lt;em&gt;tried&lt;/em&gt; to do otherwise. And it&#39;s been fun and exciting to see those random ideas come to life.&lt;/p&gt;

&lt;p&gt;And to my surprise, I&#39;ve actually re-found the joy and fairly deep flow in those long coding sessions where I&#39;m &lt;em&gt;driving agents&lt;/em&gt;! Yeah, I&#39;m shocked too. Never would have predicted this. Maybe it&#39;s not always &lt;em&gt;quite&lt;/em&gt; as deep. Certainly the actual work is different. But with my own hands-on human-in-the-loop agent dev workflow, my brain is &lt;em&gt;engaged&lt;/em&gt;. I&#39;m thinking through implementation approaches, having the agent flesh out my ideas, reviewing the output, deciding what to change and what&#39;s next and when this subtask session is done and it&#39;s time to move on. And I truly have had numerous coding sessions where I found myself deep in that same flow, and woke up at the end thrilled and excited with what I had just built, via an agent. My brain isn&#39;t off. I&#39;m not just mindlessly stamping &amp;quot;LGTM&amp;quot;. I&#39;m &lt;em&gt;thinking&lt;/em&gt;. I&#39;m &lt;em&gt;creating&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So maybe I&#39;m not writing the actual lines of code now. Not crafting the perfect elegant algorithm.&lt;/p&gt;

&lt;p&gt;But I &lt;em&gt;am&lt;/em&gt; still &amp;quot;crafting&amp;quot; the software, in a way. I&#39;m applying my taste, my judgment, my expertise. Not just in &amp;quot;here&#39;s the next ticket in my queue&amp;quot;, but very intentionally deciding what and &lt;em&gt;how&lt;/em&gt; to build the solutions, and what the right results are. I&#39;m supplying the context, figuring out the right prompts, building the guardrails, and providing the vision.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I&lt;/em&gt; can do that, because I have an entire career&#39;s worth of experience and knowledge. I don&#39;t know how juniors today are supposed to build that expertise.&lt;/p&gt;

&lt;p&gt;But hey. That was always the job.&lt;/p&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;Well. That was long. (Audience: &amp;quot;YES MARK WE &lt;em&gt;KNOW&lt;/em&gt;!&amp;quot;)&lt;/p&gt;

&lt;p&gt;Not sure what&#39;s worse - you sitting here through this whole thing, or me having written ~12K words in one single Saturday :)&lt;/p&gt;

&lt;p&gt;Like I said, I have fears. I don&#39;t have answers to a lot of big questions. It&#39;s always been a big scary world, now it seems like things really are accelerating out of control.&lt;/p&gt;

&lt;p&gt;But I never could control the rest of the world. I can only control me, and my thoughts, and my actions.&lt;/p&gt;

&lt;p&gt;I&#39;m sure some of you disagree with some of the opinions I&#39;ve stated here. That&#39;s fine. I&#39;m not trying to convince anyone. (Well okay maybe the &amp;quot;3x limits&amp;quot; and &amp;quot;rest is core, not earned&amp;quot; things.) Go do whatever works for you.&lt;/p&gt;

&lt;p&gt;A friend pointed out that this is probably just a really long rendition of the &amp;quot;stages of grief&amp;quot;. Haven&#39;t tried to map them to what I wrote, but sure, I buy that.&lt;/p&gt;

&lt;p&gt;Writing this was kinda cathartic :) I knew I had thoughts and opinions. Not sure I knew I had &lt;em&gt;this&lt;/em&gt; many just sitting there waiting to come to life :)&lt;/p&gt;

&lt;p&gt;Usually I fill my posts with dozens of links and cross-references and citations, backing up my arguments. Not gonna bother with that here. This post is about my thoughts, feelings, experiences, and opinions. You can find examples of everything I described in about every other HN and Twitter post. (I mean if you &lt;em&gt;desperately&lt;/em&gt; want actual examples email me and I&#39;ll dump a laundry list of links or something :) )&lt;/p&gt;

&lt;p&gt;If you found any of this useful at all, lemme know. I honestly have no idea how anyone&#39;s going to respond to this post. I &lt;em&gt;suspect&lt;/em&gt; it could strike a chord. We&#39;ll see.&lt;/p&gt;

&lt;p&gt;And now that we&#39;ve gone through all that, on to the part some of you were &lt;em&gt;really&lt;/em&gt; asking about :)&lt;/p&gt;

&lt;p&gt;Pop on over to &lt;a href=&#34;https://blog.isquaredsoftware.com/2026/05/ai-thoughts-part-2-agent-workflow-tools/&#34;&gt;the next post to see details on my own personal OpenCode agent setup and coding workflow&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks, y&#39;all!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Presentations: A Guide to React Compiler Rendering</title>
      <link>https://blog.isquaredsoftware.com/2026/04/presentations-react-compiler-rendering/</link>
      <pubDate>Fri, 24 Apr 2026 09:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2026/04/presentations-react-compiler-rendering/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I&#39;ve spent years explaining the basics and nuances of &lt;a href=&#34;https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-mostly-complete-guide-to-react-rendering-behavior/&#34;&gt;React&#39;s rendering behavior&lt;/a&gt;. That post is by far the most widely read resource I&#39;ve ever published, and it&#39;s helped thousands of React devs actually understand how React rendering actually works.&lt;/p&gt;

&lt;p&gt;Now, we have the &lt;a href=&#34;https://react.dev/learn/react-compiler/introduction&#34;&gt;React Compiler&lt;/a&gt;, which promises to &amp;quot;automatically optimize your React apps&amp;quot;. But how does it work? What is it doing to your components? and how does its behavior change our understanding of React&#39;s mental model?&lt;/p&gt;

&lt;p&gt;This talk recaps the core fundamentals of React rendering, and then digs into the actual React Compiler rewritten component output to demystify how it works and how it optimizes React rendering performance. From there, we look at how this flips React&#39;s default rendering behavior upside down, and how that affects our own understanding of React.&lt;/p&gt;

&lt;h2 id=&#34;react-miami-2026&#34;&gt;React Miami 2026&lt;/h2&gt;

&lt;h3 id=&#34;a-guide-to-react-compiler-rendering-slides-presentations-2026-04-react-compiler-rendering&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2026-04-react-compiler-rendering/&#34;&gt;A Guide to React Compiler Rendering: slides&lt;/a&gt;&lt;/h3&gt;

&lt;h2 id=&#34;devoxx-uk-2026&#34;&gt;Devoxx UK 2026&lt;/h2&gt;

&lt;p&gt;I gave an extended version of this talk with bonus material on React rendering:&lt;/p&gt;

&lt;h3 id=&#34;a-guide-to-react-compiler-rendering-extended-slides-presentations-2026-04-react-compiler-rendering-extended&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2026-04-react-compiler-rendering-extended/&#34;&gt;A Guide to React Compiler Rendering (extended): slides&lt;/a&gt;&lt;/h3&gt;</description>
    </item>
    
    <item>
      <title>Presentations: How I Made Immer Twice as Fast: Performance Optimization in Practice</title>
      <link>https://blog.isquaredsoftware.com/2026/03/presentations-immer-perf/</link>
      <pubDate>Thu, 26 Mar 2026 14:15:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2026/03/presentations-immer-perf/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I&#39;ve spent a lot of time debugging and doing performance optimization investigations throughout my career. It&#39;s second nature to me at this point, but a lot of developers have never really tried to investigate app performance.&lt;/p&gt;

&lt;p&gt;In late 2025 I spent multiple months investigating and optimizing performance in the Immer immutable update library.&lt;/p&gt;

&lt;p&gt;This talk covers how to approach performance investigation with a scientific approach mindset. It covers key investigation approach concepts, common perf profiling and visualization tools, and techniques to optimize code to run faster, and uses experiences from my Immer work as practical examples.&lt;/p&gt;

&lt;h2 id=&#34;react-paris-2026&#34;&gt;React Paris 2026&lt;/h2&gt;

&lt;h3 id=&#34;how-i-made-immer-twice-as-fast-slides-presentations-2026-03-immer-perf&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2026-03-immer-perf/&#34;&gt;How I Made Immer Twice as Fast: slides&lt;/a&gt;&lt;/h3&gt;

&lt;h3 id=&#34;how-i-made-immer-twice-as-fast-video-https-www-youtube-com-watch-v-5l-cysu7wgy&#34;&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=5l_cYsU7wgY&#34;&gt;How I Made Immer Twice as Fast: video&lt;/a&gt;&lt;/h3&gt;</description>
    </item>
    
    <item>
      <title>Presentations: The State of React and the Community in 2025</title>
      <link>https://blog.isquaredsoftware.com/2025/06/presentations-react-community-2025/</link>
      <pubDate>Fri, 13 Jun 2025 14:15:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2025/06/presentations-react-community-2025/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I spend a lot of time reading (and participating in) discussions in the React community, across many different sites. Over the last few years I&#39;ve seen an increasing amount of frustration and concerns from the community, questions about the motivations and intent behind React&#39;s development, and a growing disconnect between how the React team wants React to be used, and how the ecosystem is using React in practice.&lt;/p&gt;

&lt;p&gt;I&#39;ve put together this talk to explain and clarify what I&#39;m seeing argued about. My goal is to answer questions, provide background context and explanation, highlight places where I&#39;m seeing disconnects, and hopefully point out ways that things can be improved going forward.&lt;/p&gt;

&lt;h2 id=&#34;react-summit-2025&#34;&gt;React Summit 2025&lt;/h2&gt;

&lt;p&gt;I first did this talk at React Summit in June 2025. Here&#39;s the slides:&lt;/p&gt;

&lt;h3 id=&#34;the-state-of-react-and-the-community-in-2025-slides-presentations-2025-06-state-react-community&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2025-06-state-react-community/&#34;&gt;The State of React and the Community in 2025 - slides&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;I&#39;ll link the video of that talk as soon as it&#39;s available.&lt;/p&gt;

&lt;p&gt;I also got to participate in a follow-up panel discussion on &amp;quot;The State of React&amp;quot;. I&#39;ll link the video of that panel once it&#39;s available as well.&lt;/p&gt;

&lt;h2 id=&#34;more-details-the-state-of-react-and-the-community-post&#34;&gt;More Details: &amp;quot;The State of React and the Community&amp;quot; Post&lt;/h2&gt;

&lt;p&gt;Along with the talk, I&#39;ve published an extensive post on &lt;strong&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/2025/06/react-community-2025/&#34;&gt;&amp;quot;The State of React and the Community in 2025&amp;quot;&lt;/a&gt;&lt;/strong&gt;. This post goes into further details on the same topics, including more background and explanations of the pain points and concerns.&lt;/p&gt;

&lt;p&gt;Hopefully this adds more depth to the limited amount of material I was able to cover in the talk!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>The State of React and the Community in 2025</title>
      <link>https://blog.isquaredsoftware.com/2025/06/react-community-2025/</link>
      <pubDate>Fri, 13 Jun 2025 14:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2025/06/react-community-2025/</guid>
      <description>

&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;Today, the state of React and its ecosystem is complicated and fractured, with a mixture of successes, skepticism, and contention.&lt;/p&gt;

&lt;p&gt;On the positive side: React is the most widely used UI framework, and its concepts have influenced the rest of the JS ecosystem. The React team recently released React 19 after multiple years of development. This was a huge release, including official stable React Server Components support, the new &lt;code&gt;use&lt;/code&gt; hook for handling promises, multiple new form integrations, and the removal of many long-deprecated and obsolete features.&lt;/p&gt;

&lt;p&gt;However, I&#39;ve observed and experienced that &lt;strong&gt;the React community has had a growing sense of frustrations and disagreements on where React is headed, how it&#39;s developed, and the recommended approaches for using React, as well as the interactions between the React team and the community&lt;/strong&gt;. This in turn overlaps with dozens of different arguments that have ricocheted around the React and general web dev communities in the last few years, as well as specific technical concerns with how React works, comparisons with other similar JS frameworks, and how web apps should be built going forward.&lt;/p&gt;

&lt;p&gt;What makes this a lot worse is that everyone is arguing and debating a different subset of these concerns, and &lt;strong&gt;many of the stated concerns are either false or outright FUD&lt;/strong&gt;. Unfortunately, the arguments and fears have also been complicated by &lt;strong&gt;communications problems, self-inflicted marketing mis-steps, and lack of developer relations work from the React team itself&lt;/strong&gt;. All of these intertwine heavily.&lt;/p&gt;

&lt;p&gt;I&#39;ve been involved in many related discussions on social media. I&#39;ve written numerous comments both defending and critiquing the React team, explaining why they made certain decisions or how things actually happened, pushing for improvements to docs and explanations, and more.&lt;/p&gt;

&lt;p&gt;Trying to cover just &lt;em&gt;some&lt;/em&gt; some of these topics has required an extensive and detailed post (and I&#39;m not even going to touch on the &amp;quot;is React bad / how does React compare to other tools?&amp;quot; topics, which are even further out of scope). But, having spent far too many hours debating and explaining, I feel the need to write a consolidated post that covers many of these topics together.&lt;/p&gt;

&lt;p&gt;I&#39;ve also presented &lt;a href=&#34;https://blog.isquaredsoftware.com/2025/06/presentations-react-community-2025/&#34;&gt;a talk based on the topics in this post&lt;/a&gt; as well.&lt;/p&gt;

&lt;h3 id=&#34;goals&#34;&gt;Goals&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;My goals for this post are:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Give an overview of how React has developed over time&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Describe the forces driving React&#39;s development&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clarify why and how React&#39;s recent development directions have happened, and explain some of the architectural decisions behind that work&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clarify and dispel FUD and confusion regarding the motivations and intent behind React&#39;s development&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#goals&#34;&gt;Goals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#background-my-role-and-involvement-in-the-react-community&#34;&gt;Background: My Role and Involvement in the React Community&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#biases-and-caveats&#34;&gt;Biases and Caveats&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#a-brief-history-of-react&#34;&gt;A Brief History of React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#react-s-relationship-with-its-owners&#34;&gt;React&#39;s Relationship with Its Owners&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#facebook-meta&#34;&gt;Facebook / Meta&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#vercel-next-and-react&#34;&gt;Vercel, Next, and React&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#react-usage-patterns&#34;&gt;React Usage Patterns&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#standard-react-architectures&#34;&gt;Standard React Architectures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#react-build-tool-usage&#34;&gt;React Build Tool Usage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#inside-react-server-components&#34;&gt;Inside React Server Components&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#react-server-component-development-and-vercel&#34;&gt;React Server Component Development and Vercel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#rscs-frameworks-and-bundlers&#34;&gt;RSCs, Frameworks, and Bundlers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#community-concerns-and-confusion&#34;&gt;Community Concerns and Confusion&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#concern-vercel-next-and-react&#34;&gt;Concern: Vercel, Next, and React&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#concern-react-only-works-with-next&#34;&gt;Concern: React Only Works with Next&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#concern-react-might-someday-stop-working-in-client-apps&#34;&gt;Concern: React Might Someday Stop Working in Client Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#concern-why-is-react-pushing-frameworks&#34;&gt;Concern: Why Is React Pushing Frameworks?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#concern-server-component-docs-and-explanations&#34;&gt;Concern: Server Component Docs and Explanations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#takeaways-from-the-concerns&#34;&gt;Takeaways from the Concerns&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;background-my-role-and-involvement-in-the-react-community&#34;&gt;Background: My Role and Involvement in the React Community&lt;/h3&gt;

&lt;p&gt;(&lt;em&gt;aka &amp;quot;who am I, why should you trust my descriptions, and why should you care at all what my opinions are about this? 😄&amp;quot;&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I am not and never was part of the actual React team&lt;/strong&gt;. That said, &lt;strong&gt;I&#39;ve been deeply involved with the React ecosystem since 2015&lt;/strong&gt;, and it&#39;s fair to say I&#39;m as much part of the &amp;quot;React community inner circle&amp;quot; as anyone outside of Meta or Vercel.&lt;/p&gt;

&lt;p&gt;As a TL;DR:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I&#39;ve used React since 2015&lt;/li&gt;
&lt;li&gt;I maintain the Redux family of libraries, contributed to React, and been involved in React ecosystem discussions&lt;/li&gt;
&lt;li&gt;I&#39;ve written numerous lengthy tutorials on React and Redux, and frequently speak on React and Redux&lt;/li&gt;
&lt;li&gt;I&#39;ve been involved in moderating major React community sections most of that time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want the long version:&lt;/p&gt;

&lt;p&gt;&lt;details class=&#34;detailed-explanation&#34;&gt;
  &lt;summary&gt;&lt;h4&gt;My Accomplishments, Involvement, and Credentials&lt;/h4&gt;&lt;/summary&gt;&lt;/p&gt;

&lt;p&gt;I started learning React in mid-2015, after using Backbone, jQuery, and GWT to build some geospatial visualization apps. Over the next year, I went from &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/09/how-i-got-here-my-journey-into-the-world-of-redux-and-open-source/&#34;&gt;reading a few React tutorials, to lurking in the Reactiflux chat channels, to answering so many questions I became a moderator, to volunteering to write a Redux FAQ, to being handed the keys as the new Redux maintainer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ve maintained Redux since mid-2016. &lt;a href=&#34;https://blog.isquaredsoftware.com/2019/10/redux-toolkit-1.0/&#34;&gt;I created Redux Toolkit&lt;/a&gt; as the modern way to write Redux apps. While working on Redux, I&#39;ve designed and shipped &lt;a href=&#34;https://blog.isquaredsoftware.com/2018/11/react-redux-history-implementation/&#34;&gt;every version of React-Redux since v5&lt;/a&gt;. I&#39;ve had multiple conversations with the React team about how React should work with external state management libraries, and I was &lt;a href=&#34;https://github.com/reduxjs/react-redux/pull/1808&#34;&gt;the sole alpha-tester for the development of the &lt;code&gt;useSyncExternalStore&lt;/code&gt; hook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ve written hundreds of thousands of words of tutorials and blog posts teaching people how to use React and Redux and how they work, including the &lt;a href=&#34;https://redux.js.org/tutorials/essentials/part-1-overview-concepts&#34;&gt;&amp;quot;Redux Essentials&amp;quot; tutorial&lt;/a&gt; and my widely acclaimed &lt;a href=&#34;https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-mostly-complete-guide-to-react-rendering-behavior/&#34;&gt;&amp;quot;Guide to React Rendering Behavior&amp;quot; post&lt;/a&gt; (which is routinely recommended by the community as the single best explanation of how React actually works in practice). I&#39;ve written thousands of comments and answered questions across Github, the Reactiflux Discord, Reddit, Twitter, Hacker News, and Stack Overflow, about all things React and Redux and JS. I&#39;ve been referred to as &lt;a href=&#34;https://blog.isquaredsoftware.com/about/#oss-support&#34;&gt;&amp;quot;the tech support for the React community&amp;quot; and &amp;quot;the master archiver and indexer of all things React&amp;quot;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;ve &lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/&#34;&gt;spoken at numerous React-related conferences&lt;/a&gt; on topics ranging from &lt;a href=&#34;https://blog.isquaredsoftware.com/2023/08/presentations-react-rendering-behavior/&#34;&gt;how React works&lt;/a&gt; to &lt;a href=&#34;https://blog.isquaredsoftware.com/2024/11/presentations-maintaining-community/&#34;&gt;best practices and lessons learned maintaining widely used OSS libraries&lt;/a&gt;. I&#39;ve been on &lt;a href=&#34;https://blog.isquaredsoftware.com/presentations&#34;&gt;numerous podcasts discussing React and Redux&lt;/a&gt;, including the ongoing &lt;a href=&#34;https://www.reactiflux.com/transcripts/tmir-2024-12&#34;&gt;&amp;quot;This Month in React&amp;quot; podcast hosted by the Reactiflux Discord&lt;/a&gt; where we talk about the latest news, releases, and insights on React and the community.&lt;/p&gt;

&lt;p&gt;I was part of the initial private React Hooks preview feedback group, and the invite-only-but-public React 18 Working Group, where we gave feedback on the design, docs, and usage aspects for both releases.&lt;/p&gt;

&lt;p&gt;I&#39;m an administrator in &lt;a href=&#34;https://www.reactiflux.com&#34;&gt;the Reactiflux Discord&lt;/a&gt;, and have been the primary active moderator in &lt;a href=&#34;https://reddit.com/r/reactjs/&#34;&gt;the /r/reactjs subreddit&lt;/a&gt; for several years.&lt;/p&gt;

&lt;p&gt;I&#39;ve dug inside of React, the repo, and the internals, including &lt;a href=&#34;https://github.com/facebook/react/pull/26446&#34;&gt;submitting a PR that generated production sourcemaps for React builds&lt;/a&gt;, and &lt;a href=&#34;https://blog.isquaredsoftware.com/2023/10/presentations-react-devtools-replay/&#34;&gt;using time-travel debugging to integrate the React DevTools into Replay&#39;s DevTools&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;/details&gt;&lt;/p&gt;

&lt;p&gt;The point of listing those accomplishments is to establish that &lt;strong&gt;I have a long history and expertise around how React is developed, what&#39;s going on in the React community, what&#39;s happening &lt;em&gt;inside&lt;/em&gt; the React team, and trying to help people learn React and Redux.&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&#34;biases-and-caveats&#34;&gt;Biases and Caveats&lt;/h3&gt;

&lt;p&gt;Since this is the Internet, I&#39;ll try to preempt some concerns folks might have with me writing this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I am most definitely &lt;em&gt;not&lt;/em&gt; always right, and I&#39;m definitely going to end up describing some things incorrectly due to limited knowledge, misunderstandings, or over-summarizing&lt;/strong&gt;. That said, &lt;strong&gt;I&#39;m writing this as a best-faith effort to describe history, motivations, and behaviors as honestly and accurately as I can&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;in more detail:&lt;/p&gt;

&lt;p&gt;&lt;details class=&#34;detailed-explanation&#34;&gt;
  &lt;summary&gt;&lt;h4&gt;More Detailed Biases and Caveats&lt;/h4&gt;&lt;/summary&gt;&lt;/p&gt;

&lt;p&gt;Since I maintain Redux, that does bias my own opinions to how React gets used, as well as the kinds of problems I deal with.&lt;/p&gt;

&lt;p&gt;While I&#39;ve used React in some form consistently since 2015, my own experiences using React have become more limited and more niche over time. Most of the React apps I&#39;ve worked on have been internal tools with limited distribution, and mostly &amp;quot;desktop-style apps in a browser&amp;quot; - in other words, true SPAs without even any routing or CRUD-type behavior. I did work on &lt;em&gt;one&lt;/em&gt; CRUD/dashboard-style app, but it was limited in scope. I&#39;ve never built apps with huge audiences, never used SSR or RSCs in practice, never had to worry about i18n or other large-scaling concerns. I&#39;ve spent much of my time working on libraries and developer tools, and much less time in the day-to-day of &amp;quot;typical&amp;quot; React app development.&lt;/p&gt;

&lt;p&gt;I&#39;ve read and been involved in inside-baseball React community discussions that the average React app dev never hears or cares about.&lt;/p&gt;

&lt;p&gt;I&#39;ve had personal interactions with the React team online and in person that have been both very positive, and very negative and frustrating. These color my own perspectives. But, I&#39;ve also had enough discussions with other members of the community to have good confidence that many others share my concerns and opinions.&lt;/p&gt;

&lt;p&gt;My normal writing style involves linking as many references and sources as possible. For this post I&#39;ll &lt;em&gt;try&lt;/em&gt; to do that, but a lot of these historical descriptions and observations will be difficult to find specific sources for, so please trust that I&#39;m doing my best to describe them accurately even if summarized.&lt;/p&gt;

&lt;p&gt;&lt;/details&gt;&lt;/p&gt;

&lt;p&gt;So, with all those caveats stated, let&#39;s get going.&lt;/p&gt;

&lt;h2 id=&#34;a-brief-history-of-react&#34;&gt;A Brief History of React&lt;/h2&gt;

&lt;p&gt;The early history is covered better in other places, including &lt;a href=&#34;https://www.youtube.com/watch?v=8pDqJVdNa44&#34;&gt;the React Documentary&lt;/a&gt;, but to provide some context for the rest of this post:&lt;/p&gt;

&lt;p&gt;React was developed internally at Facebook around 2011-12, and open-sourced in 2013. It gathered a handful of external contributors, but &lt;strong&gt;until recently all actual development was done by the React core team inside of Facebook / Meta&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While the core concepts of React have always stayed the same (components, props, state, data flow), the implementation details, public APIs, and breadth of scope have shifted over time. React went from creating components with &lt;code&gt;createClass&lt;/code&gt;, to ES6 &lt;code&gt;class MyComponent extends React.Component&lt;/code&gt;, to &lt;code&gt;function MyComponent()&lt;/code&gt;. React split from web-only to supporting mobile with React Native, then became customizable for other platforms such as WebGL (&lt;code&gt;react-three-fiber&lt;/code&gt;) and CLI (&lt;code&gt;ink&lt;/code&gt;) via a customizable &lt;code&gt;react-reconciler&lt;/code&gt; core. The internals were completely rewritten to a new &amp;quot;Fiber&amp;quot; architecture, unlocking further architectural changes. Function components gained the ability to have state and side effects with the release of hooks in 2018.&lt;/p&gt;

&lt;p&gt;For years, &lt;strong&gt;React pitched itself as a minimal UI-focused rendering library&lt;/strong&gt; (&amp;quot;the &#39;V&#39; in &#39;MVC&#39;&amp;quot;, &amp;quot;A JS library for building user interfaces&amp;quot;). Other frameworks like Angular or Ember were fully batteries included and had significant opinions about how to build and structure apps, but the React team left all of that up to the community. This led to a massive explosion in the ecosystem, both for better and worse. For any conceivable library category, there were dozens of competing tools solving overlapping problems: state management (Redux, Mobx, Zustand, ....), CSS and styles (Styled-Components, Emotion, CSS Modules, ....), data fetching (React Query, Apollo, SWR, RTK Query, ....), build tools (Babel, Webpack, ESBuild, Vite, Parcel, ....), and hundreds more.&lt;/p&gt;

&lt;p&gt;React users have always had to begin a project by picking and choosing a set of libraries to solve the various use cases in their app. Additionally, React could be used in numerous ways: rendering every single element on the client side in a Single-Page App (SPA), rendering multiple subtrees attached to a server-rendered page, on the server as part of a Multi-Page App (MPA), and much more. The flexibility and variety of ecosystem options has been both a strength and a weakness. You &lt;em&gt;get&lt;/em&gt; to choose the exact combination of tools you need for your project... but you also &lt;em&gt;have&lt;/em&gt; to choose a combination of tools. That leads to decision fatigue, variations in project codebases, and constant changes in what tools are commonly used.&lt;/p&gt;

&lt;p&gt;Overall, &lt;strong&gt;both the React library and the React team intentionally stayed unopinonated&lt;/strong&gt;. They didn&#39;t want to play favorites with specific tools in the ecosystem, their time and attention was focused on building React itself, and they still viewed the scope of React as being somewhat narrow.&lt;/p&gt;

&lt;p&gt;That ecosystem variety provided flexibility, but also complexity. This was especially true with build tools. Early React tutorials often spent multiple pages at the start explaining &amp;quot;here&#39;s how to configure Webpack and Babel&amp;quot;, before you could even write your first React component. This led the React team to build a pre-packaged build tool configuration called Create React App. CRA was a CLI tool that could generate a new React project from a template, and built it with a a highly complex and customized Webpack + Babel config that was designed to make it simple to start a new project with a single command. That config was kept encapsulated as a black box, to hide the complexity out of sight.&lt;/p&gt;

&lt;p&gt;React never had a built-in method for data fetching, so it was standard to use third-party libraries to fetch and cache data. React did have server rendering (SSR) capabilities early on, with methods to render React component trees to HTML as strings or streams, but those had to be used manually in server handlers. Over time, other prepackaged React build systems and &amp;quot;frameworks&amp;quot; became popular. Next.js also wrapped Webpack, but added more features like built-in server rendering with filesystem routing conventions and page-based data fetching. Gatsby generated sites from GraphQL-based data sources. Later, Remix added server &amp;quot;data loaders&amp;quot; and pushed for more HTML/platform-based usage conventions.&lt;/p&gt;

&lt;p&gt;In late 2020, the React team announced a prototype for &amp;quot;React Server Components&amp;quot;, an architectural approach that allowed async React components to run on the server and fetch data, then render child components and pass the children and data to React running on the client. This was intended to be a React-idiomatic solution to data fetching, and marked a significant shift from React&#39;s original &amp;quot;just the view on the client&amp;quot; historical pitch. During the development of RSCs, some of the React core team members left Meta and joined Vercel, creators of Next.js. They continued building out the initial RSC implementation, and worked with the Next dev team to rearchitect Next with the new &amp;quot;App Router&amp;quot;, the first production implementation of RSCs.&lt;/p&gt;

&lt;p&gt;The React team also spent 2020-2023 completely rewriting the React docs site from scratch. The new React docs at &lt;a href=&#34;https://react.dev&#34;&gt;react.dev&lt;/a&gt; have a fantastic tutorial that walks through React&#39;s concepts step-by-step, with numerous in-page examples in runnable sandboxes, as well as much improved API reference pages.&lt;/p&gt;

&lt;p&gt;When the new docs came out, the React team made a significant shift in how they recommended using React. Previously, the old React docs &lt;a href=&#34;https://legacy.reactjs.org/docs/create-a-new-react-app.html#recommended-toolchains&#34;&gt;recommended starting with CRA if you were learning or building a client-side SPA&lt;/a&gt;, or pointed to a couple other frameworks like Next or Gatsby if you needed SSR or static sites. With the new docs, the React team changed their approach, and begin specifically and strongly recommending &amp;quot;you &lt;em&gt;should&lt;/em&gt; use a framework to write React apps - they have routing, data fetching, and build capabilities built in&amp;quot;. This also tied into the work to build RSCs. As part of this, the &lt;a href=&#34;https://web.archive.org/web/20250125034212/https://react.dev/learn/start-a-new-react-project&#34;&gt;&amp;quot;Start a New React Project&amp;quot; page&lt;/a&gt; specifically warned &lt;em&gt;against&lt;/em&gt; using React without a framework. Next was listed prominently on that docs page - ordered first on the &amp;quot;Frameworks&amp;quot; list (for the Pages router), and then mentioned further down as the only available RSC implementation. React team members working at Vercel were quoted as saying &lt;a href=&#34;https://x.com/acdlite/status/1549853625673023488&#34;&gt;&amp;quot;I think of the upcoming Next.js release as the &#39;real&#39; React 18 release&amp;quot;&lt;/a&gt;,&lt;/p&gt;

&lt;p&gt;This tied into Create React App having effectively died around 2022. It had been unmaintained for some time prior. When a PR was filed recommending &amp;quot;mark CRA as deprecated and recommend Vite&amp;quot;, Dan Abramov wrote an detailed comment explaining &lt;a href=&#34;https://github.com/reactjs/react.dev/pull/5487#issuecomment-1409720741&#34;&gt;why CRA was created, problems with CRA, the rise of frameworks, and the shift of React&#39;s vision&lt;/a&gt;. In response, the React community collectively moved on from CRA, and the docs stopped recommending it, but nothing was done to officially mark it as &amp;quot;deprecated&amp;quot;.&lt;/p&gt;

&lt;h2 id=&#34;react-s-relationship-with-its-owners&#34;&gt;React&#39;s Relationship with Its Owners&lt;/h2&gt;

&lt;p&gt;Today, React&#39;s development work is sponsored and owned by two companies: Meta (formerly Facebook), and Vercel.&lt;/p&gt;

&lt;h3 id=&#34;facebook-meta&#34;&gt;Facebook / Meta&lt;/h3&gt;

&lt;p&gt;From the beginning, React was a Facebook / Meta-owned project. The code was open-sourced, and anyone &lt;em&gt;could&lt;/em&gt; submit a PR, but essentially all dev work was done by the React team at Meta.&lt;/p&gt;

&lt;p&gt;This had significant impacts on how React was developed. React core team meetings were generally internal, as were any roadmaps. The React team would often prototype a half-dozen ideas for a problem space, then get app teams at Meta to try them out for vetting. By the time a new React feature was announced, it had gone through many internal iterations and been validated in actual usage. At the same time, the React team has also been responsible for supporting Meta&#39;s app teams with bug fixes and other support.&lt;/p&gt;

&lt;p&gt;Despite this, the React team has had a fairly free hand in how they&#39;ve developed the library. While React was created inside Facebook for Facebook usage, the React team itself has decided their roadmap and long-term vision for how the library should work. For the most part, React&#39;s actual development process and roadmap has been driven themselves, rather than by other influences inside Facebook / Meta. That said, they also do have to justify their own performance and how projects benefit Meta.&lt;/p&gt;

&lt;p&gt;Meta&#39;s own use of React is both widespread and distinct from how the community uses it. Meta has its own massive server infrastructure, including standard techniques for data fetching, routing, security, and more. Meta invented the GraphQL protocol, as well as the Relay GraphQL client layer, and frequently uses those with their React code. This means that Meta&#39;s React use rarely needs third-party libraries for routing, state management, styling, or other problems common to the rest of the community.&lt;/p&gt;

&lt;h3 id=&#34;vercel-next-and-react&#34;&gt;Vercel, Next, and React&lt;/h3&gt;

&lt;p&gt;Vercel is primarily a hosting platform for web apps. They mostly make money by having more people host apps on their platform, and charge for the convenience of easier usage. They have put massive amounts of engineering time into building the Next.js framework (as well as supporting other frameworks), and making it trivial to set up and deploy Next apps on Vercel infrastructure.&lt;/p&gt;

&lt;p&gt;Vercel&#39;s CEO, Guillermo Rauch, is a long-time believer in React and its capabilities, as shown by his 2015 blog post &lt;a href=&#34;https://rauchg.com/2015/pure-ui&#34;&gt;Pure UI&lt;/a&gt; that talks about the power of React&#39;s rendering model.&lt;/p&gt;

&lt;p&gt;In late 2021, &lt;a href=&#34;https://vercel.com/blog/supporting-the-future-of-react&#34;&gt;React team lead Sebastian Markbage left Meta to join Vercel&lt;/a&gt;. This was the first instance of full-time React core team members working anywhere other than Meta. He was later joined by core team member Andrew Clark and former React org lead Tom Occhino. The React team had already done significant prototyping on RSC functionality in React internally. Seb helped design the Next.js App Router, and Vercel had additional engineers begin contributing to React&#39;s core and server rendering capabilities.&lt;/p&gt;

&lt;p&gt;Today, &lt;a href=&#34;https://react.dev/community/team&#34;&gt;the React team is split between Meta and Vercel&lt;/a&gt; (with a majority still at Meta), plus a handful of team members or consistent contributors externally.&lt;/p&gt;

&lt;h2 id=&#34;react-usage-patterns&#34;&gt;React Usage Patterns&lt;/h2&gt;

&lt;h3 id=&#34;standard-react-architectures&#34;&gt;Standard React Architectures&lt;/h3&gt;

&lt;p&gt;The React (and ReactDOM in particular) library itself does not care how you use it within a page. You can serve a near-empty HTML placeholder and render a React tree that generates the entire page contents on the client side, as a Single-Page App (&amp;quot;SPA&amp;quot;). You can use React for server rendering (&amp;quot;SSR&amp;quot;), where the server dynamically responds to each request, or static site generation (&amp;quot;SSG&amp;quot;), where you pre-generate static HTML pages at build time. You can serve a static or server-rendered HTML page using any language or framework (Python + Django, Ruby + Rails, PHP + WordPress, .NET, etc), and sprinkle bits of React throughout the page to add interactivity.&lt;/p&gt;

&lt;p&gt;That said, by 2015 React was most commonly used for client-side SPA app architectures. As with everything, these had tradeoffs. They made it easier to generate the page contents (it&#39;s all React components), had faster user interactions (show a different component on click or route change instead of a full page refresh), and enabled richer app experiences. It didn&#39;t matter what the backend was (JS, Java, PHP, .NET, Python) - just expose a JSON API and fetch data. However, they also were slower to load the initial page bundle, and client-side routing could lead to uncanny interactions vs native browser behavior.&lt;/p&gt;

&lt;p&gt;Data fetching on those clients was initially fairly manual, and required careful logic in side effects (such as triggering a fetch in &lt;code&gt;componentDidMount&lt;/code&gt; to request data when a component first rendered). This was often done with Redux-based logic to handle the fetching and caching, although that code was typically full of boilerplate and complexity. Later, purpose-built data fetching libraries like React Query, Apollo, SWR, and RTK Query greatly simplified data fetching on the client, providing purpose-built &lt;code&gt;useQuery&lt;/code&gt; hooks and prebuilt caching mechanisms.&lt;/p&gt;

&lt;p&gt;Frameworks like Next and Remix provided standardized approaches to server-rendering React, with built-in filesystem routing conventions. However, there was no convention for server-based data fetching. Next invented a &lt;code&gt;getServerSideProps&lt;/code&gt; mechanism to specify an async function for fetching alongside a component. Remix later invented &amp;quot;loaders&amp;quot; with a similar architecture. Neither of those &lt;em&gt;felt&lt;/em&gt; particularly native to React.&lt;/p&gt;

&lt;p&gt;This has led to a general mindset shift in the React ecosystem. There&#39;s more of a push for SSR-based architectures to improve page loading experiences and minimize the amount of JS needed for a page, as well as removing the need to use data fetching libraries on the client side. The React team has argued loudly against &amp;quot;waterfalls&amp;quot; in data fetching in order to improve page loading performance, and even client-side routers like React Router and TanStack Router offer ways to prefetch data at the route/page level rather than triggering fetches nested deep in the component tree.&lt;/p&gt;

&lt;h3 id=&#34;react-build-tool-usage&#34;&gt;React Build Tool Usage&lt;/h3&gt;

&lt;p&gt;It&#39;s worth looking at the download stats for several major React related build tools and frameworks to get a sense of usage scale in the ecosystem over time and today.&lt;/p&gt;

&lt;p&gt;Loosely put, today the major options for tools in terms of mindshare and/or downloads are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://nextjs.org&#34;&gt;Next.js&lt;/a&gt; (SSR / SSG / RSC / SPA)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://remix.run/&#34;&gt;Remix&lt;/a&gt; / React-Router v7 (SSR / SSG / SPA)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://vite.dev/&#34;&gt;Vite&lt;/a&gt; (SPA)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://create-react-app.dev/&#34;&gt;Create React App&lt;/a&gt; (SPA)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It&#39;s also worth noting that Vite itself started off from the Vue ecosystem, but has become a standardized and widely used build tool with support for many different client-side frameworks. It also has a plugin ecosystem, including the plugin for React support, and has become the build tool of choice for various frameworks. That includes Remix / React-Router, which recently switched from using ESBuild internally to providing a Vite plugin to enable their SSR and SSG support.&lt;/p&gt;

&lt;p&gt;Here&#39;s &lt;a href=&#34;https://npm-stat.com/charts.html?package=react-dom&amp;amp;package=next&amp;amp;package=%40vitejs%2Fplugin-react&amp;amp;package=%40remix-run%2Freact&amp;amp;package=react-scripts&amp;amp;from=2018-01-01&amp;amp;to=2025-05-31&#34;&gt;a graph of NPM downloads for these tools over the last few years&lt;/a&gt;, with ReactDOM for scale:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.isquaredsoftware.com/images/2025-06-react-community-2025/react-frameworks-usage.png&#34; alt=&#34;NPM download stats&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Until recently, the React docs also listed Gatsby as a recommended framework for web and Expo as the only recommended framework for React Native. Gatsby effectively died after being purchased by Netlify. Meanwhile, Astro is a more generic static-site-focused tool that supports many frameworks including React. Here&#39;s their download stats for comparison:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.isquaredsoftware.com/images/2025-06-react-community-2025/react-frameworks-usage-2.png&#34; alt=&#34;NPM download stats 2&#34; /&gt;&lt;/p&gt;

&lt;p&gt;A few takeaways from those stats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js is most widely used&lt;/li&gt;
&lt;li&gt;Vite&#39;s React plugin has grown steadily, and is now the second most widely used React-related build tool&lt;/li&gt;
&lt;li&gt;CRA usage peaked in mid-2023 and has been declining since, but still sees considerable usage&lt;/li&gt;
&lt;li&gt;Remix has strong word of mouth at this point, but is relatively smaller. React Router is very widely used, but the newer versions that support &amp;quot;framework mode&amp;quot; aren&#39;t as widely adopted yet.&lt;/li&gt;
&lt;li&gt;Gatsby never had anywhere near as much traction as Next, CRA, or Vite, and Astro recently surpassed it.&lt;/li&gt;
&lt;li&gt;Astro is not React-specific, but has roughly the same downloads as Remix does&lt;/li&gt;
&lt;li&gt;Vite + CRA together equal Next&#39;s usage, which shows that there&#39;s still a strong demand for plain SPA projects in the React ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;inside-react-server-components&#34;&gt;Inside React Server Components&lt;/h2&gt;

&lt;h3 id=&#34;react-server-component-development-and-vercel&#34;&gt;React Server Component Development and Vercel&lt;/h3&gt;

&lt;p&gt;The React team had experience with server-based data fetching from Meta&#39;s infrastructure, as well as automatically splitting JS bundles and lazy-loading code. However, unlike previous React feature development, their options for iterating on and shipping RSCs inside of Meta were limited. Meta&#39;s existing server infra and technologies made it difficult to fully design RSCs in a way that the rest of the community could actually use and benefit from.&lt;/p&gt;

&lt;p&gt;It&#39;s worth noting that &lt;strong&gt;React Server Components were the &lt;em&gt;React&lt;/em&gt; team&#39;s vision for how to write React apps in the future&lt;/strong&gt;. As far as I know, this was not something that either Meta or Vercel came up with, or pushed the React team to build.&lt;/p&gt;

&lt;p&gt;There had been intermittent discussion and complaints about &amp;quot;all of React&#39;s development is done by Meta employees&amp;quot; for years, and occasional comments of &amp;quot;it might be nice if there was a &#39;React Foundation&#39;, or folks outside Meta working directly on React&amp;quot;. While I don&#39;t know the actual discussions involved, from the outside my understanding is that &lt;strong&gt;the React team approached Vercel and pitched their vision of RSCs, and Vercel agreed to be the new proving ground as RSCs were developed&lt;/strong&gt;. This led to Sebastian Markbage (and later Andrew Clark) moving from Meta to Vercel, and the Next team spending huge amounts of time, money, and engineering effort to design and build the Next App Router as the first working implementation of RSCs.&lt;/p&gt;

&lt;p&gt;As &lt;a href=&#34;https://www.reddit.com/r/reactjs/comments/1kg3yqh/rsc_for_astro_developers_overreacted/mr2bl62/&#34;&gt;Dan Abramov described it&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Vercel team has allocated many full-time engineer/years to implementing the things the React team wanted. That’s not to speak of directly taking the technical direction from the React team. Next.js was more or less rewritten from scratch.
&lt;br /&gt;
The person designing Next.js now is the person who invented React Hooks. So if anything, &lt;strong&gt;it was more of a case of React team “taking over” the Next.js direction&lt;/strong&gt; rather than “favouring” it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There &lt;em&gt;were&lt;/em&gt; efforts made to get other frameworks and companies involved in that process. Shopify&#39;s Hydrogen framework did some very early testing and feedback of RSCs, but eventually concluded it wasn&#39;t a good fit for them. The Remix team was asked several times if they&#39;d like to be involved, but initially decided to focus on their own approaches.&lt;/p&gt;

&lt;p&gt;As a result, &lt;strong&gt;Next became the first (and effectively still the &lt;em&gt;only&lt;/em&gt;) &amp;quot;production-ready&amp;quot; RSC implementation&lt;/strong&gt;. Today several other frameworks are working on RSC integration (including Parcel, React Router, and Waku), but Next&#39;s App Router is the only widespread option for using RSCs today.&lt;/p&gt;

&lt;h3 id=&#34;rscs-frameworks-and-bundlers&#34;&gt;RSCs, Frameworks, and Bundlers&lt;/h3&gt;

&lt;p&gt;I commonly see questions like &amp;quot;why do RSCs require a bundler or framework? Why can&#39;t they just be built into React?&amp;quot;.&lt;/p&gt;

&lt;p&gt;React&#39;s existing server-rendering methods like &lt;code&gt;renderToString&lt;/code&gt; and &lt;code&gt;renderToPipeableStream&lt;/code&gt; could be called anywhere, such as an Express route handler. However, architecturally RSCs are much more complex. RSC functionality requires parsing code to look for the &lt;code&gt;&#39;use client&#39;&lt;/code&gt; and &lt;code&gt;&#39;use server&#39;&lt;/code&gt; directives, then transforming that code to insert the appropriate calls to register Client Components and server functions with the RSC core functionality. That requires tight integration with a bundler, so that it can correctly determine the full module graph for both server and client and compile them appropriately.&lt;/p&gt;

&lt;p&gt;Additionally, while the React core implements the actual RSC functionality, and provides primitives for sending serialized components and data between client and server, it&#39;s up to a framework to actually &lt;em&gt;call&lt;/em&gt; and use those primitives in the right place. This is primarily about integration with a router, so that the client app receives the right lazy-loaded Client Components, and calls the right endpoints with actions and data.&lt;/p&gt;

&lt;p&gt;This also means that every framework&#39;s use and implementation of RSCs will be different. Next made very specific implementation decisions with the App Router for handling layouts and routing. Other frameworks and build tools like Waku, Parcel, and React Router are already making some very different design decisions.&lt;/p&gt;

&lt;p&gt;Overall, RSCs are an unusual hybrid feature. The main functionality is built directly into the React core packages, but that functionality cannot be used until it is integrated into some kind of bundler/router/framework combination.&lt;/p&gt;

&lt;h2 id=&#34;community-concerns-and-confusion&#34;&gt;Community Concerns and Confusion&lt;/h2&gt;

&lt;p&gt;With all that history and context in mind, let&#39;s move on to answering (and hopefully clarifying or dispelling) several frequently repeated concerns that are either confused, FUD, or outright conspiracy theories.&lt;/p&gt;

&lt;h3 id=&#34;concern-vercel-next-and-react&#34;&gt;Concern: Vercel, Next, and React&lt;/h3&gt;

&lt;p&gt;There&#39;s now an extremely common viewpoint that &amp;quot;Vercel is driving React development, with a goal of making more money hosting sites&amp;quot;. As an example, this is the highest-upvoted comment from a Reddit thread earlier this year:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Vercel has effectively taken over React and has a primary interest of pushing users to NextJS, deployed on Vercel, so Vercel shareholders get richer.&amp;quot;
&lt;a href=&#34;https://www.reddit.com/r/react/comments/1iarj85/xbluesky_react_recently_feels_biased_against_vite/m9cb51h/&#34;&gt;https://www.reddit.com/r/react/comments/1iarj85/xbluesky_react_recently_feels_biased_against_vite/m9cb51h/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This ties into several other related points of concern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next is recommended first in the React docs, and the Next App Router is also mentioned as the main example under &amp;quot;Which features make up the React team’s full-stack architecture vision?&amp;quot;&lt;/li&gt;
&lt;li&gt;Next is still the only production implementation of RSCs&lt;/li&gt;
&lt;li&gt;React team members have been quoted as saying that &lt;a href=&#34;https://x.com/acdlite/status/1549853625673023488&#34;&gt;&amp;quot;This Next release is the real React 18&amp;quot;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I can see how people might come to this conclusion. Vercel hired several React team members, who are working on both React itself and Next. Timeline-wise, this did naturally coincide with the development of RSCs, and the new shift towards pushing users to use a framework... and look, the &amp;quot;obvious&amp;quot; framework is indeed Next! Meanwhile, Vercel has put massive amounts of money and effort into making Next easy to deploy and host on Vercel. It&#39;s &lt;em&gt;possible&lt;/em&gt; to host Next elsewhere, but there&#39;s always been features that didn&#39;t work or things were hard to configure.&lt;/p&gt;

&lt;p&gt;All that said, from everything I&#39;ve seen, this take generally inverts the cause and effect, and is mostly FUD. Yes, of course Vercel has invested in efforts they think will end up making them money. But, per above, everything I&#39;ve seen describing Seb and Andrew going to Vercel and the development process of RSCs says that it was the &lt;em&gt;React team&lt;/em&gt; that drove this set of changes.&lt;/p&gt;

&lt;p&gt;RSCs were the React team&#39;s vision. They couldn&#39;t effectively be prototyped and tested inside of Meta, so for the first time there was a need for some other sponsor to invest in the development and provide a setting to iterate on the design. I don&#39;t know the specifics of how it happened, but my understanding is that the React team convinced Vercel to buy into the React team&#39;s vision, &lt;em&gt;and&lt;/em&gt; let them drive rearchitecting Next to design the App Router approach that would match that vision.&lt;/p&gt;

&lt;p&gt;There certainly has been &lt;em&gt;some&lt;/em&gt; amount of &amp;quot;Next needs this&amp;quot;-type changes to React. I know I saw several PRs getting merged in the React repo the night before one of the NextConfs that had a significant Next version announcement (possibly the stable App Router in 13.4?). But, it was still the React team members doing that work.&lt;/p&gt;

&lt;p&gt;At this point, the React team is split. The majority are still at Meta, but the members at Vercel are key to the core implementation. I&#39;ve read that &amp;quot;React team meetings are still the same as always&amp;quot;, but I wouldn&#39;t be surprised if there&#39;s &lt;em&gt;some&lt;/em&gt; additional complexity from splitting that way.&lt;/p&gt;

&lt;p&gt;All that said, I do think that &amp;quot;Vercel took over React&amp;quot; is wrong, and it&#39;s more like &amp;quot;part of React core migrated to Vercel and convinced Vercel to align with React&#39;s vision&amp;quot;. I also don&#39;t see evidence that &amp;quot;Vercel&amp;quot; is driving the design of React, or that the emphasis on frameworks and RSCs is with the specific intent to make Vercel money.&lt;/p&gt;

&lt;h3 id=&#34;concern-react-only-works-with-next&#34;&gt;Concern: React Only Works with Next&lt;/h3&gt;

&lt;p&gt;I&#39;ve seen multiple comments online with people saying, either seriously or wonderingly, that &amp;quot;React only works with Next now&amp;quot;.&lt;/p&gt;

&lt;p&gt;This is easily refuted. &lt;strong&gt;Even just looking at &lt;a href=&#34;https://react.dev/learn/start-a-new-react-project&#34;&gt;the &amp;quot;Start a New React Project&amp;quot; page&lt;/a&gt; shows other frameworks that are &lt;em&gt;not&lt;/em&gt; Next&lt;/strong&gt;, as well as the somewhat infamous &amp;quot;Can I use React without a framework?&amp;quot; section.&lt;/p&gt;

&lt;p&gt;Clearly this is a complete misunderstanding of how React works.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;But&lt;/em&gt;, it also says something about how confused the messaging around React, &amp;quot;use frameworks&amp;quot;, and Vercel&#39;s influence has become.&lt;/p&gt;

&lt;p&gt;I&#39;ll tack on the very related &amp;quot;Should I use Next or React?&amp;quot; question, which also pops up frequently. The literal reading is that &amp;quot;Next&amp;quot; and &amp;quot;React&amp;quot; are different things. This is also clearly wrong. Next is a framework that &lt;em&gt;uses&lt;/em&gt; the React libraries. It&#39;s a superset, not a competitor. I assume that what most people &lt;em&gt;mean&lt;/em&gt; is &amp;quot;should I use Next, or a client-side SPA like CRA or Vite?&amp;quot;, but they don&#39;t have the vocabulary to state that clearly.&lt;/p&gt;

&lt;p&gt;Again, that shows how much confusion there is around the boundaries here.&lt;/p&gt;

&lt;h3 id=&#34;concern-react-might-someday-stop-working-in-client-apps&#34;&gt;Concern: React Might Someday Stop Working in Client Apps&lt;/h3&gt;

&lt;p&gt;I&#39;ve seen this one come up repeatedly too. The concern is that &amp;quot;if the React team is putting &lt;em&gt;this&lt;/em&gt; much emphasis and work into features that require a server, does that mean that &lt;em&gt;someday&lt;/em&gt; the client-side functionality might change or go away?&amp;quot;.&lt;/p&gt;

&lt;p&gt;I can understand &lt;em&gt;why&lt;/em&gt; people have this fear. It&#39;s driven by the huge shift in tone and emphasis from the React team, as well as the amount of effort they&#39;ve put into server-side functionality.&lt;/p&gt;

&lt;p&gt;However, it&#39;s also clearly impossible that this will ever happen. &lt;strong&gt;React&#39;s client rendering functionality &lt;em&gt;will not&lt;/em&gt; ever go away!&lt;/strong&gt; Just the fact that Meta itself has millions of lines of existing React code shows that. On top of that, the React team &lt;em&gt;has&lt;/em&gt; always been extremely good about code-level backwards compatibility - describing breaking changes, keeping around deprecated features for years before finally removing them, providing migration guides and codemods.&lt;/p&gt;

&lt;p&gt;It&#39;s also worth noting that many of the features in React 19 and 19.1 are client-only. If anything, the community has over-estimated the amount of effort put into server-side functionality, and missed the amount of effort put into client-side features.&lt;/p&gt;

&lt;h3 id=&#34;concern-why-is-react-pushing-frameworks&#34;&gt;Concern: Why Is React Pushing Frameworks?&lt;/h3&gt;

&lt;p&gt;And that leads us to our next argument: &lt;strong&gt;why is the React team so dead-set on making all React users use frameworks, to the point of telling people they&#39;re doing it wrong otherwise?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a concern that I have a lot more sympathy and agreement for. I just said that I don&#39;t think they&#39;re saying &amp;quot;use frameworks&amp;quot; with a goal of &amp;quot;get people using Next and hosting on Vercel&amp;quot;, so what&#39;s the reasoning?&lt;/p&gt;

&lt;h4 id=&#34;react-team-opinions-on-frameworks&#34;&gt;React Team Opinions on Frameworks&lt;/h4&gt;

&lt;p&gt;Andrew Clark&#39;s &lt;a href=&#34;https://x.com/acdlite/status/1617667097424986114&#34;&gt;tweets from Jan 2023 state the intent pretty clearly&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you use React, you should be using a React framework. If your existing app doesn&#39;t use a framework, you should incrementally migrate to one. If you&#39;re creating a new React project, you should use a framework from the beginning&lt;/p&gt;

&lt;p&gt;Your React framework of choice should have built-in solutions for data fetching, routing, and server rendering. Frameworks don&#39;t treat these as independent concerns — they provide deeply integrated solutions that are easy to use and result in excellent performance out of the box.&lt;/p&gt;

&lt;p&gt;If you choose to forgo a framework, what you&#39;re really choosing is to build your own bespoke framework, one that&#39;s likely much worse than what you&#39;d get off the shelf. Even if you think your bespoke framework is better than the alternatives today, will that be true in a year?&lt;/p&gt;

&lt;p&gt;It takes lots of time and energy to keep up with the state of the art. Are you ready to become a framework maintainer? Or are there better things you should be doing with your time?&lt;/p&gt;

&lt;p&gt;The main thing that has changed since then is that the frameworks got really, really good. It used to be that plain React + Webpack was as good or better than all-in-one frameworks. IMO, that&#39;s no longer true&lt;/p&gt;

&lt;p&gt;The question isn&#39;t whether it&#39;s possible to build a React app without using a framework. You&#39;ll always have that option.
The question is whether your homegrown set up can compete with the industry leaders — on features, on performance, on DX.
The bar is constantly being raised.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Similarly, in Dan Abramov&#39;s &lt;a href=&#34;https://github.com/reactjs/react.dev/pull/5487#issuecomment-1409720741&#34;&gt;explanation of why they were considering CRA deprecated&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create React App solved only one side of the problem. It provided a good (at the time!) development experience, but it didn&#39;t impose enough structure to help you leverage the strong sides of the web for a good user experience. You could try to solve these problems yourself, but that would involve &amp;quot;ejecting&amp;quot; and significantly customizing your setup, which defeated the point of Create React App. Every truly efficient React setup was custom, different, and unachievable with Create React App.&lt;/p&gt;

&lt;p&gt;These user experience problems are not specific to Create React App. They are not even specific to React. For example, apps created from the Vite homepage templates for Preact, Vue, Lit, and Svelte suffer from all of the same problems. These problems are inherent to purely client-side apps with no static site generation (SSG) or server-side rendering (SSR).&lt;/p&gt;

&lt;p&gt;If you build entire apps with React, being able to use SSG/SSR is important. The lack of support for them in Create React App is glaring. But it&#39;s not the only area where Create React App is behind&lt;/p&gt;

&lt;p&gt;React itself is only a library. It does not dictate how to do routing or data fetching. Neither does Create React App. Unfortunately, this means that neither React alone nor Create React App, as originally designed, can solve these problems. As you can see, this isn&#39;t about a single missing feature. These features — server-side rendering and static generation, data fetching, bundling, and routing — are interconnected.&lt;/p&gt;

&lt;p&gt;Times changed. Now it&#39;s getting increasingly difficult to recommend a solution where you are locked into not having these features. Even if you don&#39;t use all of them immediately, they should be available for you when you need them. You shouldn&#39;t have to migrate to a different template and restructure all of your code to take advantage of them. Similarly, not all data fetching or code splitting needs to be route-based. But it&#39;s a good default that should be available to most React apps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I&#39;ve also had conversations with the React team where they directly told me that they have heard many of the external complaints about React apps having bad loading times and overall poor performance. So, the frameworks emphasis is a direct response to that, with the goal of getting more apps to have decent performance by default.&lt;/p&gt;

&lt;p&gt;Based on that, we can summarize the React team&#39;s stance as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frameworks have built-in approaches for data fetching, routing, and server rendering, that are designed to work together&lt;/li&gt;
&lt;li&gt;Those are all provided out of the box, so you don&#39;t have to spend time picking and choosing pieces (that may not work well together)&lt;/li&gt;
&lt;li&gt;Frameworks lead to better performance by default, due to build setups and better data fetching patterns&lt;/li&gt;
&lt;li&gt;Additionally, React Server Components &lt;em&gt;require&lt;/em&gt; integration into a framework to work properly&lt;/li&gt;
&lt;li&gt;Those concerns are critical to how the React team feels React &lt;em&gt;should&lt;/em&gt; be used today&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, it&#39;s a combination of an ideological stance, a belief that &amp;quot;this will save you time and effort&amp;quot;, and also a belief that &amp;quot;most React apps follow similar patterns and need similar solutions&amp;quot;.&lt;/p&gt;

&lt;h4 id=&#34;frameworks-ssr-and-spas&#34;&gt;Frameworks, SSR, and SPAs&lt;/h4&gt;

&lt;p&gt;Also, note the specific mention of &amp;quot;server rendering&amp;quot;. In general, both the React team and other key members of the ecosystem (such as Ryan Florence and Michael Jackson of Remix / React Router) have put heavy emphasis on the need to do server rendering to avoid &amp;quot;waterfalls&amp;quot; of data fetching on the client (such as &lt;code&gt;&amp;lt;List&amp;gt;&lt;/code&gt; fetching a set of items, rendering its children, &lt;code&gt;&amp;lt;ListItem&amp;gt;&lt;/code&gt; doing its own fetch after mount, etc ). Frameworks like Next and Remix have been specifically designed to support server rendering out of the box.&lt;/p&gt;

&lt;p&gt;The justifications for SSR around &amp;quot;faster initial page loads&amp;quot;, &amp;quot;less JS on the client&amp;quot;, and &amp;quot;avoiding waterfalls&amp;quot; all make reasonable sense. I also agree that client-side SPAs have been used in a lot of places they probably shouldn&#39;t have been (same as with Redux, really), and that it can make sense to start with a framework even if you don&#39;t need &lt;em&gt;all&lt;/em&gt; the functionality right away, so that you can take advantage of those features when you decide you need them.&lt;/p&gt;

&lt;p&gt;I&#39;ll note that Next and Remix &lt;em&gt;do&lt;/em&gt; have &lt;a href=&#34;https://nextjs.org/docs/pages/building-your-application/deploying/static-exports&#34;&gt;&amp;quot;SPA / export&amp;quot; modes&lt;/a&gt; that just output static JS/HTML assets, so it &lt;em&gt;is&lt;/em&gt; possible to use them to create a purely client-side app with no Node server process needed. However, those are not the defaults, and I would assume most of the community is unaware that is even an option.&lt;/p&gt;

&lt;h4 id=&#34;framework-push-lacks-nuance&#34;&gt;Framework Push Lacks Nuance&lt;/h4&gt;

&lt;p&gt;Given all that: I &lt;em&gt;understand&lt;/em&gt; why the React team has decided to recommend frameworks as a default. I think it&#39;s a reasonable opinion, and valid intentions to improve the average React app.&lt;/p&gt;

&lt;p&gt;But I also feel that &lt;strong&gt;the &amp;quot;recommendation&amp;quot; has turned into an overly-broad prescription that doesn&#39;t give enough credit to the variety of ways React is used in practice throughout the ecosystem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There&#39;s many good reasons to use a full-stack React framework, but also plenty of reasons &lt;em&gt;not&lt;/em&gt; to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frameworks add many additional features and functionality, but that&#39;s also added complexity to learn, making them less suitable for beginners that are just trying to get a handle on how to use React at all.&lt;/li&gt;
&lt;li&gt;The added complexity can also be a trap that leads to confusion, such as accidentally using Context or hooks in Server Components (which throws errors)&lt;/li&gt;
&lt;li&gt;Many companies may not be running JS backends, and may even have rules and restrictions against that&lt;/li&gt;
&lt;li&gt;Frameworks with server functionality do require specific hosting to run, whereas a pure SPA can be trivially hosted anywhere that serves static HTML and JS (including Github Pages and Amazon S3)&lt;/li&gt;
&lt;li&gt;While the &lt;em&gt;need&lt;/em&gt; to pick and choose your libraries has often been a source of frustration for React users, it does enable customizing projects to meet your specific needs. Opinionated frameworks remove the need to make most of those decisions, but can also limit your ability to customize behavior later.&lt;/li&gt;
&lt;li&gt;The emphasis on &amp;quot;server rendering&amp;quot; clearly helps &lt;em&gt;some&lt;/em&gt; kinds of apps, but not all - there are plenty of apps that only need to live on the client side.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&#34;docs-recommendations-matter&#34;&gt;Docs Recommendations Matter&lt;/h4&gt;

&lt;p&gt;The React team has said that &amp;quot;the docs are aimed at beginners&amp;quot;, so they want to keep the list of recommended tools and options fairly simple to avoid confusion. This is a very reasonable stance.&lt;/p&gt;

&lt;p&gt;They&#39;ve &lt;em&gt;also&lt;/em&gt; said that &amp;quot;anyone who&#39;s experienced enough to know to use Vite doesn&#39;t need to see it listed in the docs anyway&amp;quot; (paraphrased). That&#39;s &lt;em&gt;technically&lt;/em&gt; true.&lt;/p&gt;

&lt;p&gt;However, it&#39;s not just beginners that read the docs, and what the docs recommend does have an influence as a stamp of official approval. That&#39;s a large part of why the React team had historically avoided recommending specific libraries or techniques.&lt;/p&gt;

&lt;p&gt;If we refer back to the framework / build tool usage stats, today Vite React and CRA usage outweighs Next, and it&#39;s clear that SPA usage is still at &lt;em&gt;least&lt;/em&gt; half of the React ecosystem. The docs recommendations ought to reflect that usage.&lt;/p&gt;

&lt;h4 id=&#34;dismissal-of-the-ecosystem&#34;&gt;Dismissal of the Ecosystem&lt;/h4&gt;

&lt;p&gt;When the new React docs came out, the only mention of non-framework options was an expandable details section labeled &lt;a href=&#34;https://web.archive.org/web/20230318003653/https://react.dev/learn/start-a-new-react-project#can-i-use-react-without-a-framework&#34;&gt;&amp;quot;Can I Use React Without A Framework?&amp;quot;&lt;/a&gt;, with several paragraphs saying &amp;quot;yes, but we don&#39;t think it&#39;s a good idea&amp;quot;.&lt;/p&gt;

&lt;p&gt;And buried at the end of that section was this statement:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you’re still not convinced, or your app has unusual constraints not served well by these frameworks and you’d like to roll your own custom setup, we can’t stop you—go for it! Grab react and react-dom from npm, set up your custom build process with a bundler like Vite or Parcel, and add other tools as you need them for routing, static generation or server-side rendering, and more.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, not only did the new setup page &lt;em&gt;not&lt;/em&gt; list Create React App, but the closest equivalent tool (Vite) wasn&#39;t even listed as a meaningful option in the outer section of the page. Instead, it was buried as a mere mention at the bottom of this expandable explanation.&lt;/p&gt;

&lt;p&gt;I&#39;d also say that the phrase &amp;quot;unusual constraints&amp;quot; is very poor here. SPAs had been the standard architecture in the React community since the beginning. CRA and Vite are commonly used. How is building an SPA suddenly an &amp;quot;unusual constraint&amp;quot;? There are &lt;em&gt;many&lt;/em&gt; reasons to want an SPA, from architectural to business reasons to simplicity of learning. Those aren&#39;t &amp;quot;unusual&amp;quot; - those are all common use cases.&lt;/p&gt;

&lt;p&gt;And beyond that... note the phrase &amp;quot;&lt;strong&gt;we can&#39;t stop you&lt;/strong&gt;&amp;quot;. That phrase stuck out to many people as poor phrasing that came across as dismissive of the community, and an indication that the React team was relegating SPAs as an unsupported approach, overnight.&lt;/p&gt;

&lt;p&gt;As an example of this, here&#39;s a quote from a debate about the &amp;quot;frameworks&amp;quot; emphasis in the docs from mid-2023:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In some ways React is having its AngularJS moment. Teams are using this time of instability and uncertainty to shop around for alternatives. We certainly are.&lt;br /&gt;
React is great. It&#39;s the strong server &amp;amp; framework alignment tone change that&#39;s concerning to communities. The server-neutral aspects that made it what it is today suddenly feel second-class. (SPA routers &amp;amp; loaders are a mess &amp;amp; underserved!)&lt;br /&gt;
It&#39;s not about React or Vite. It&#39;s the ecosystem. It&#39;s painful to realize that React won&#39;t encourage the traditional &amp;quot;non-framework&amp;quot; as strongly as the &amp;quot;new ways&amp;quot;. The &amp;quot;React without a framework&amp;quot; section is tucked away in the docs and depressing.&lt;br /&gt;
As a non-Node backend company we see those docs as a sign that we don&#39;t align with React&#39;s primary direction anymore. Framework endorsements are a big enough change to cause teams to reevaluate entire stacks. React is great, but its influence has limits on architecture.
It&#39;s not &amp;quot;wrong&amp;quot; for React to go this direction. But we can&#39;t pretend that non-Framework React usage is now a second-class concern. How long until it&#39;s not a viable option? It&#39;s uncomfortable. So, we look for safer bets. What would you recommend a non-node backend company do?&lt;br /&gt;
&lt;a href=&#34;https://x.com/vyrotek/status/1649097699696992256&#34;&gt;https://x.com/vyrotek/status/1649097699696992256&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&#34;fixing-the-docs-recommendations&#34;&gt;Fixing the Docs Recommendations&lt;/h4&gt;

&lt;p&gt;When the React team finally &lt;a href=&#34;https://react.dev/blog/2025/02/14/sunsetting-create-react-app&#34;&gt;announced CRA as deprecated in early 2025&lt;/a&gt; (after I helped push them to fix it and make that deprecation official), the &lt;a href=&#34;https://github.com/reactjs/react.dev/pull/7495&#34;&gt;initial docs update&lt;/a&gt; included a new &amp;quot;Building Your Own Framework&amp;quot; page. The concept was that picking your own router and data fetching approach was equivalent to cobbling together a bespoke framework that wouldn&#39;t be as good as a &amp;quot;real&amp;quot; framework.&lt;/p&gt;

&lt;p&gt;I understand the mental model here, but this is also rather dismissive of both the way the ecosystem had been building apps, and of people&#39;s ability to choose their own options.&lt;/p&gt;

&lt;p&gt;As an example, Vite creator &lt;a href=&#34;https://x.com/youyuxi/status/1892000761778929931&#34;&gt;Evan You posted his take&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;it feels the React team&#39;s hesitance on Vite (and build tooling in general) is how it aligns with their vision of React (i.e. RSC being the recommended paradigm), and how much influence / connection they have with the said tools to make sure the integration works as they designed and can adapt to design iterations.
...&lt;br /&gt;
I apologize if this is not what the React team is thinking, but it’s my honest guess because I am just as puzzled as many React users by what took it so long for Vite to be better acknowledged as a recommended tool.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I ended up &lt;a href=&#34;https://github.com/reactjs/react.dev/pull/7618&#34;&gt;filing a draft PR to revamp the setup pages&lt;/a&gt; to improve the tone, add nuance in recommending project setup tools, and offer some architectural guidance on choosing approaches. That PR got closed, but the React team did cherry-pick some of the ideas and phrasing over into a new PR.&lt;/p&gt;

&lt;p&gt;Ultimately, they ended up with a &lt;a href=&#34;https://web.archive.org/web/20250526084038/https://react.dev/learn/build-a-react-app-from-scratch&#34;&gt;&amp;quot;Building a React App from Scratch&amp;quot; setup page&lt;/a&gt; that is fairly reasonable. It recognizes SPAs and picking your own tools as a valid approach, lists Vite / Parcel / RSPack as suggested build tools, points to some routers and data fetching libraries, and provides some actual useful guidance to users trying to set up a project.&lt;/p&gt;

&lt;p&gt;It&#39;s unfortunate that it took us multiple years to get the docs to that point :( Much of the confusion and angst could have been avoided if the React team had applied some of the community-recommended phrasing changes soon after the new docs were released.&lt;/p&gt;

&lt;h3 id=&#34;concern-server-component-docs-and-explanations&#34;&gt;Concern: Server Component Docs and Explanations&lt;/h3&gt;

&lt;p&gt;One of the big pain points and sources of confusion around React Server Components is that official docs and info has been scattered and unfortunately lacking.&lt;/p&gt;

&lt;p&gt;The React team &lt;a href=&#34;https://react.dev/blog/2020/12/21/data-fetching-with-react-server-components&#34;&gt;originally announced RSCs with an explanation video in Dec 2020&lt;/a&gt;, and that was followed by &lt;a href=&#34;https://github.com/reactjs/rfcs/blob/main/text/0188-server-components.md&#34;&gt;a lengthy and detailed RFC doc explaining RSCs&lt;/a&gt;. These did do a decent job of explaining the background and primary motivations.&lt;/p&gt;

&lt;p&gt;However, the development process of RSCs, combined with the fact that it&#39;s up to frameworks to implement design choices, meant that the actual React docs have never meaningfully documented RSCs.&lt;/p&gt;

&lt;p&gt;It took almost 2 years for &lt;a href=&#34;https://nextjs.org/blog/next-13&#34;&gt;Next 13.0&lt;/a&gt; to come out with the first official beta release of RSCs in the form of the new App Router, and another 6 months until &lt;a href=&#34;https://nextjs.org/blog/next-13-4&#34;&gt;Next 13.4 officially declared the App Router as &amp;quot;stable&amp;quot; and ready for production&lt;/a&gt; in May 2023. Vercel and Next have a small but very active devrel team, and by the time of Next 13.4&#39;s release, &lt;a href=&#34;https://web.archive.org/web/20230502235021/https://beta.nextjs.org/docs&#34;&gt;they had done a sizeable rewrite of the Next docs to cover the then-new App Router, available as &amp;quot;beta&amp;quot; docs&lt;/a&gt;. That included some docs pages that talked about using RSCs, &lt;a href=&#34;https://web.archive.org/web/20230422084216/https://beta.nextjs.org/docs/data-fetching/fundamentals&#34;&gt;under the &amp;quot;Data Fetching&amp;quot; category&lt;/a&gt;, as well as later detailed blog posts like &lt;a href=&#34;https://vercel.com/blog/understanding-react-server-components&#34;&gt;Understanding React Server Components&lt;/a&gt;. These were excellent resources, with very helpful explanations of architecture and concepts.&lt;/p&gt;

&lt;p&gt;And yet, even though the RSC functionality was part of React itself, &lt;strong&gt;the React docs didn&#39;t have &lt;em&gt;any&lt;/em&gt; information on RSCs&lt;/strong&gt;. Not &amp;quot;What Are RSCs&amp;quot;, not &amp;quot;How Do I Use an RSC&amp;quot;, and &lt;em&gt;definitely&lt;/em&gt; not &amp;quot;How Do I Integrate My Library With RSCs&amp;quot;. Vercel&#39;s team did a good job documenting their actual product and some of the overlap with React, but it was extremely confusing to people why there was no info or explanations about RSCs in the actual React docs themselves (which, timeline-wise, had just officially launched a couple months earlier).&lt;/p&gt;

&lt;p&gt;There&#39;s been lots of discussion from individual React team members on social media, responding to questions, arguing in favor of RSCs as a concept, and trying to flesh out sales pitches for RSCs. But as of today, the only official core docs page on RSCs is &lt;a href=&#34;https://react.dev/reference/rsc/server-components&#34;&gt;API Reference: Server Components&lt;/a&gt;. This page is, honestly, confusing and not particularly helpful. It&#39;s definitely not an &amp;quot;API reference&amp;quot; content-wise, and the content doesn&#39;t have any real context introducing RSCs or explaining when and how to use them - it&#39;s a grab bag of random topics.&lt;/p&gt;

&lt;p&gt;There &lt;em&gt;have&lt;/em&gt; been a number of excellent external blog posts explaining various aspects of RSCs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dan Abramov has written &lt;a href=&#34;https://overreacted.io&#34;&gt;numerous fantastic posts explaining the mental model of RSCs and the problems they solve&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Vercel published a great &lt;a href=&#34;https://vercel.com/blog/understanding-react-server-components&#34;&gt;&amp;quot;Understanding React Server Components&amp;quot;&lt;/a&gt; intro blog post&lt;/li&gt;
&lt;li&gt;Daniel Saewitz wrote &lt;a href=&#34;https://saewitz.com/server-components-give-you-optionality&#34;&gt;Server Components Give You Optionality&lt;/a&gt; explaining how they&#39;re an addition to your toolbox&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the kind of information that &lt;em&gt;should&lt;/em&gt; be in the React core docs - explanations of RSC concepts and why you might want to use them, independent of how any specific framework implemented RSCs.&lt;/p&gt;

&lt;p&gt;Related to this: the community has taken away the idea that &amp;quot;RSCs are the future of React&amp;quot;, and that &amp;quot;the React team &lt;em&gt;wants&lt;/em&gt; us to use RSCs all the time everywhere&amp;quot;. In reality, I&#39;ve seen React team members explicitly say on social media that &amp;quot;RSCs are optional, we just want people to understand them properly&amp;quot;. Given that confusion, it seems like making that point specifically in the docs is important.&lt;/p&gt;

&lt;p&gt;Personally, I&#39;d like to see an entire section on RSCs added to the React core docs, with pages like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&amp;quot;Intro to RSCs&amp;quot;&lt;/li&gt;
&lt;li&gt;Mental model&lt;/li&gt;
&lt;li&gt;Use cases / when to choose RSCs&lt;/li&gt;
&lt;li&gt;Technical data flow / architecture&lt;/li&gt;
&lt;li&gt;Adoption / migration&lt;/li&gt;
&lt;li&gt;FAQ&lt;/li&gt;
&lt;li&gt;Framework implementor&#39;s guide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having those docs pages would not make all the questions go away. Lots of people don&#39;t even read the docs in the first place :) But having those topics covered officially &lt;em&gt;would&lt;/em&gt; make it visible, and it would act as a resource that could be used to answer these questions whenever they come up on social media.&lt;/p&gt;

&lt;h2 id=&#34;takeaways-from-the-concerns&#34;&gt;Takeaways from the Concerns&lt;/h2&gt;

&lt;p&gt;I don&#39;t think it&#39;s the React team&#39;s job to spend all their time dispelling FUD on the internet. Lots of people will have opinions, many of them will be differing or wrong.&lt;/p&gt;

&lt;p&gt;That said, it&#39;s striking that there&#39;s a strongly consistent theme of &amp;quot;all of this emphasis on frameworks and servers is being forced on us to make Vercel money&amp;quot;. It&#39;s wrong, but there&#39;s enough circumstantial evidence to lead people to that belief, and the React team&#39;s actions and statements have to some extent reinforced that belief instead of disproving it. Unfortunately, at this point it seems to be a meme that is permanently embedded in the community, and I don&#39;t think we&#39;re going to make it go away.&lt;/p&gt;

&lt;p&gt;It&#39;s also genuinely concerning that users are worried or assuming potential problems with how React &lt;em&gt;might&lt;/em&gt; change or stop working in the future, especially when those concerns are clearly wrong and easily disprovable. You can continue to use React exactly as you always have, and all of the RSC / server functionality is entirely additive and optional.&lt;/p&gt;

&lt;p&gt;The internet being what it is, even a blog post on the actual React blog that explicitly refuted those statements wouldn&#39;t change a lot of people&#39;s minds. But it does feel like &lt;em&gt;maybe&lt;/em&gt; some of the worst of that could have been avoided with better developer relations work from the React org - more time spent reading the concerns, acknowledging that they exist and understanding where they&#39;re coming from, and trying clarify and answer them.&lt;/p&gt;

&lt;p&gt;I do feel that the push for &amp;quot;frameworks&amp;quot; has been genuinely well intentioned, but also too broad and ultimately dismissive of the variety of usage patterns in the ecosystem. Yes, it&#39;s hard to write docs and provide recommendations that offer nuance, and it&#39;s understandable to try to keep things simple to target beginners and nudge the ecosystem in a better direction... but part of being a maintainer is recognizing and supporting the variety of ways your tools are used by the community.&lt;/p&gt;

&lt;p&gt;We &lt;em&gt;did&lt;/em&gt; finally end up with a reasonable set of React project setup docs that have useful instructions on setting up a project yourself and recognize that as a valid approach. It&#39;s unfortunate that it took us years to get to that point, and that the React team essentially ignored the very vocal feedback from the community on how to improve that section of the docs. The docs would still really benefit from more advice on how to approach choosing an appropriate tool and architecture for your app.&lt;/p&gt;

&lt;p&gt;Similarly, the lack of official core docs info on RSC concepts and tradeoffs has contributed to the confusion. I strongly feel that covering those topics would be a huge improvement in people&#39;s understanding of RSCs and the resulting discourse.&lt;/p&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;This hopefully answers a lot of questions about how and why React has developed the way it has, what the influences are on React&#39;s development process, the main goals of the React team, and where React usage patterns stand today.&lt;/p&gt;

&lt;p&gt;I also hope I&#39;ve been able to dispel some of the confusion and FUD around the React team&#39;s motivations and reasons for pushing in specific directions. It&#39;s fine if people disagree with the technical directions, or decide that they don&#39;t need React Server Components or to migrate to a larger framework. But the React team&#39;s intentions are valid and genuine here.&lt;/p&gt;

&lt;p&gt;It&#39;s really hard to maintain widely-used libraries and satisfy the variety of needs and usage patterns in the community. I do think the React team has done a good job overall. Unfortunately, the places where the communications have been poor and the issues with the docs have been a big contributing factor to a lot of the frustration and angst in the community.&lt;/p&gt;

&lt;p&gt;Going forward, I&#39;m hopeful that we can find ways to improve that communication, and maybe even get more of the community involved in improving the docs.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Presentations: Maintaining a Library and a Community</title>
      <link>https://blog.isquaredsoftware.com/2024/11/presentations-maintaining-community/</link>
      <pubDate>Thu, 21 Nov 2024 21:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2024/11/presentations-maintaining-community/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The main thesis of this talk is that maintainers do a &lt;em&gt;lot&lt;/em&gt; more than just write features and fix bugs, and that really most of what we do involves thinking about and interacting with the users of our library. That includes answering support questions, writing docs, thinking about how versioning and backwards compatibility will impact people, and a lot more.&lt;/p&gt;

&lt;p&gt;Hopefully this proves useful to other maintainers, and peels back the curtain on what it&#39;s like to maintain a widely-used library.&lt;/p&gt;

&lt;h2 id=&#34;react-summit-us-2024&#34;&gt;React Summit US 2024&lt;/h2&gt;

&lt;p&gt;I first did this talk at React Summit US in November 2024:&lt;/p&gt;

&lt;h3 id=&#34;maintaining-a-library-and-a-community-video-https-gitnation-com-contents-maintaining-a-library-and-a-community&#34;&gt;&lt;a href=&#34;https://gitnation.com/contents/maintaining-a-library-and-a-community&#34;&gt;Maintaining a Library and a Community - video&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;And here&#39;s the slides:&lt;/p&gt;

&lt;h3 id=&#34;maintaining-a-library-and-a-community-slides-presentations-2024-11-maintaining-community&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2024-11-maintaining-community/&#34;&gt;Maintaining a Library and a Community - slides&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;I also got to participate in a panel discussion on &amp;quot;The Future of React&amp;quot;, with members of the React team and the community. This was a pretty good discussion:&lt;/p&gt;

&lt;h3 id=&#34;the-future-of-react-panel-video-https-gitnation-com-contents-panel-discussion-future-of-react&#34;&gt;&lt;a href=&#34;https://gitnation.com/contents/panel-discussion-future-of-react&#34;&gt;The Future of React panel - video&lt;/a&gt;&lt;/h3&gt;

&lt;h2 id=&#34;ndc-oslo-2025&#34;&gt;NDC Oslo 2025&lt;/h2&gt;

&lt;p&gt;For NDC Oslo, I significantly expanded and updated the content and slides. Part of that is that I had an entire hour time slot instead of just 20 minutes, but also I thought of a lot more things to say :)&lt;/p&gt;

&lt;h3 id=&#34;maintaining-a-library-and-a-community-slides-presentations-2025-05-maintaining-community&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2025-05-maintaining-community/&#34;&gt;Maintaining a Library and a Community - slides&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;Video should be available online about a month after the conference, and I&#39;ll update this post once it&#39;s available.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://www.youtube.com/live/42kUqbV3wIc?si=asXlCveJ_o660adX&#34;&gt;https://www.youtube.com/live/42kUqbV3wIc?si=asXlCveJ_o660adX&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>React Advanced 2024: Designing Effective Documentation</title>
      <link>https://blog.isquaredsoftware.com/2024/11/presentations-designing-documentation/</link>
      <pubDate>Thu, 21 Nov 2024 20:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2024/11/presentations-designing-documentation/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;My remote presentation for React Advanced 2024 was on &amp;quot;Designing Effective Documentation: Lessons Learned Writing the Redux Docs&amp;quot;.&lt;/p&gt;

&lt;p&gt;I&#39;ve spent a &lt;em&gt;lot&lt;/em&gt; of my time working on the Redux docs, and it is in fact &lt;a href=&#34;https://blog.isquaredsoftware.com/2016/09/how-i-got-here-my-journey-into-the-world-of-redux-and-open-source/&#34;&gt;how I got my start working on Redux!&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Hopefully this proves useful to other folks writing docs for tools and libraries.&lt;/p&gt;

&lt;h3 id=&#34;designing-effective-documentation-video-https-gitnation-com-contents-designing-effective-documentation-lessons-learned-building-the-redux-docs&#34;&gt;&lt;a href=&#34;https://gitnation.com/contents/designing-effective-documentation-lessons-learned-building-the-redux-docs&#34;&gt;Designing Effective Documentation - video&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;And here&#39;s the slides:&lt;/p&gt;

&lt;h3 id=&#34;designing-effective-documentation-slides-presentations-2024-10-designing-documentation&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2024-10-designing-documentation/&#34;&gt;Designing Effective Documentation - slides&lt;/a&gt;&lt;/h3&gt;</description>
    </item>
    
    <item>
      <title>React Summit 2024: Why Use Redux Today?</title>
      <link>https://blog.isquaredsoftware.com/2024/07/presentations-why-use-redux/</link>
      <pubDate>Tue, 09 Jul 2024 23:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2024/07/presentations-why-use-redux/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I had the chance to speak at both React Connection Paris in April and React Summit Amsterdam in June, and at both conferences I gave a talk on &amp;quot;Why Use Redux Today?&amp;quot;.&lt;/p&gt;

&lt;p&gt;Both of those had the same core content, but I tweaked and updated the slides for React Summit.&lt;/p&gt;

&lt;h3 id=&#34;why-use-redux-today-video-https-portal-gitnation-org-contents-why-you-should-use-redux-in-2024&#34;&gt;&lt;a href=&#34;https://portal.gitnation.org/contents/why-you-should-use-redux-in-2024&#34;&gt;Why Use Redux Today? - video&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;and the earlier livestream:&lt;/p&gt;

&lt;h3 id=&#34;why-use-redux-today-livestream-https-www-youtube-com-live-zzl5rejx3-q-si-szox9hgk4kkr1-wn-t-11802&#34;&gt;&lt;a href=&#34;https://www.youtube.com/live/ZZl5REJX3-Q?si=sZox9HGk4KKr1-Wn&amp;amp;t=11802&#34;&gt;Why Use Redux Today? - livestream&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;And here&#39;s the slides:&lt;/p&gt;

&lt;h3 id=&#34;why-use-redux-today-slides-presentations-2024-06-why-use-redux-today&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2024-06-why-use-redux-today/&#34;&gt;Why Use Redux Today? - slides&lt;/a&gt;&lt;/h3&gt;</description>
    </item>
    
    <item>
      <title>React Summit US 2023: What&#39;s New in Redux Toolkit 2.0</title>
      <link>https://blog.isquaredsoftware.com/2023/11/presentations-rtk-2.0-new/</link>
      <pubDate>Mon, 13 Nov 2023 23:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2023/11/presentations-rtk-2.0-new/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I gave a lightning talk at React Summit US, and did a quick run-through of what&#39;s changing in RTK 2.0.&lt;/p&gt;

&lt;p&gt;I&#39;ve linked the livestream at the right timestamp for now, and will link the final video when it&#39;s live.&lt;/p&gt;

&lt;h3 id=&#34;what-s-new-in-redux-toolkit-2-0-video-https-www-youtube-com-live-gk3ilmqkmg4-si-ulkg2j5rgrc00mr3-t-17718&#34;&gt;&lt;a href=&#34;https://www.youtube.com/live/gk3ILmQKMg4?si=UlKg2j5rgrc00Mr3&amp;amp;t=17718&#34;&gt;What&#39;s New in Redux Toolkit 2.0 - video&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;And here&#39;s the slides:&lt;/p&gt;

&lt;h3 id=&#34;what-s-new-in-redux-toolkit-2-0-slides-presentations-2023-11-rtk-2-0-new&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2023-11-rtk-2.0-new/&#34;&gt;What&#39;s New in Redux Toolkit 2.0 - slides&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;(and totally unrelated to my talk, had the chance to lead a Carnival Parade of costumed characters as part of Kathleen McMahon&#39;s demonstration of &amp;quot;why you should never include a carousel in your design system!&amp;quot;)&lt;/p&gt;

&lt;h3 id=&#34;kathleen-mcmahon-carnival-video-https-www-youtube-com-live-pnptgva7pqk-si-03rvfmqn20-lzlzx-t-22261&#34;&gt;&lt;a href=&#34;https://www.youtube.com/live/PNPtgva7PQk?si=03RvfmqN20_lZLzX&amp;amp;t=22261&#34;&gt;Kathleen McMahon: Carnival!!! - video&lt;/a&gt;&lt;/h3&gt;</description>
    </item>
    
    <item>
      <title>React Advanced 2023 - Building Better React DevTools with Replay Time Travel</title>
      <link>https://blog.isquaredsoftware.com/2023/10/presentations-react-devtools-replay/</link>
      <pubDate>Tue, 24 Oct 2023 10:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2023/10/presentations-react-devtools-replay/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I work at &lt;a href=&#34;https://replay.io&#34;&gt;Replay.io&lt;/a&gt;, and I&#39;ve spent all of this year building some incredibly advanced React debugging features that make use of our time-traveling backend API. The biggest one is our React DevTools integration. Early in 2023, I wrote a post for the Replay.io blog on &lt;a href=&#34;https://blog.replay.io/how-we-rebuilt-react-devtools-with-replay-routines&#34;&gt;How We Rebuilt React DevTools with Replay Routines&lt;/a&gt;, which recapped the initial working version. I&#39;ve spent much of this year improving on that and building other related features.&lt;/p&gt;

&lt;p&gt;At React Advanced, I got to share details on how the React DevTools work internally, and dive into how we extract React DevTools component tree data from recorded React apps using a combination of custom Chrome modifications and backend post-processing &amp;quot;routines&amp;quot; that leverage our time-travel API. Along the way, I showed off some crazy tricks like serializing JS functions as strings, sourcemapping original component names from production apps, and generating sourcemaps for React itself!&lt;/p&gt;

&lt;p&gt;I also got to participate in a group panel discussion about Open Source, including questions about how we got involved and what it&#39;s like to &amp;quot;compete&amp;quot; with other OSS projects.&lt;/p&gt;

&lt;p&gt;I&#39;ve linked the livestream at the right timestamp for now, and will link the final video when it&#39;s live.&lt;/p&gt;

&lt;h3 id=&#34;building-better-react-devtools-with-replay-time-travel-video-https-www-youtube-com-watch-v-jvv3huromu8-start-2896&#34;&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=jvV3HurOMu8&amp;amp;start=2896&#34;&gt;Building Better React DevTools with Replay Time Travel - video&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;And here&#39;s the slides:&lt;/p&gt;

&lt;h3 id=&#34;building-better-react-devtools-with-replay-time-travel-slides-presentations-2023-10-react-devtools-replay&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2023-10-react-devtools-replay/&#34;&gt;Building Better React DevTools with Replay Time Travel - slides&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;and the OSS Panel video:&lt;/p&gt;

&lt;h3 id=&#34;react-advanced-panel-open-source-video-https-www-youtube-com-watch-v-tuqy9cp38ue-t-8001s&#34;&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=tUqY9CP38uE&amp;amp;t=8001s&#34;&gt;React Advanced Panel: Open Source - video&lt;/a&gt;&lt;/h3&gt;</description>
    </item>
    
    <item>
      <title>React Rally 2023 - A (Brief) Guide to React Rendering Behavior</title>
      <link>https://blog.isquaredsoftware.com/2023/08/presentations-react-rendering-behavior/</link>
      <pubDate>Wed, 16 Aug 2023 14:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2023/08/presentations-react-rendering-behavior/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;My extensive post &lt;a href=&#34;https://blog.isquaredsoftware.com/2020/05/blogged-answers-a-mostly-complete-guide-to-react-rendering-behavior/&#34;&gt;&amp;quot;A (Mostly) Complete Guide to React Rendering Behavior&amp;quot;&lt;/a&gt; is the most popular and widely appreciated post I&#39;ve written. After the recent updates to cover React 18, it&#39;s now around 10,900 words long!&lt;/p&gt;

&lt;p&gt;I recently had a chance to give a talk based on that post for React Advanced in 2022 and React Rally in 2023.&lt;/p&gt;

&lt;h2 id=&#34;react-rally-2023&#34;&gt;React Rally 2023&lt;/h2&gt;

&lt;p&gt;I&#39;ll link the video once it&#39;s available.&lt;/p&gt;

&lt;h3 id=&#34;a-brief-guide-to-react-rendering-behavior-slides-presentations-2023-08-guide-react-rendering-behavior&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2023-08-guide-react-rendering-behavior&#34;&gt;A (Brief) Guide to React Rendering Behavior - slides&lt;/a&gt;&lt;/h3&gt;

&lt;h3 id=&#34;a-brief-guide-to-react-rendering-behavior-livestream-video-https-www-youtube-com-live-pxcs9iahcie-si-ld9pmqdagb5gi0w7-t-20666&#34;&gt;&lt;a href=&#34;https://www.youtube.com/live/pxCs9IAhciE?si=lD9PmQdaGB5GI0W7&amp;amp;t=20666&#34;&gt;A (Brief) Guide to React Rendering Behavior - livestream video&lt;/a&gt;&lt;/h3&gt;

&lt;h2 id=&#34;react-advanced-2022&#34;&gt;React Advanced 2022&lt;/h2&gt;

&lt;h3 id=&#34;a-brief-guide-to-react-rendering-behavior-video-https-portal-gitnation-org-contents-a-guide-to-react-rendering-behavior&#34;&gt;&lt;a href=&#34;https://portal.gitnation.org/contents/a-guide-to-react-rendering-behavior&#34;&gt;A (Brief) Guide to React Rendering Behavior - video&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;And here&#39;s the slides:&lt;/p&gt;

&lt;h3 id=&#34;a-brief-guide-to-react-rendering-behavior-slides-presentations-2022-10-guide-react-rendering-behavior&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2022-10-guide-react-rendering-behavior/&#34;&gt;A (Brief) Guide to React Rendering Behavior - slides&lt;/a&gt;&lt;/h3&gt;</description>
    </item>
    
    <item>
      <title>Blogged Answers: My Experience Modernizing Packages to ESM</title>
      <link>https://blog.isquaredsoftware.com/2023/08/esm-modernization-lessons/</link>
      <pubDate>Tue, 08 Aug 2023 10:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2023/08/esm-modernization-lessons/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;h2 id=&#34;table-of-contents&#34;&gt;Table of Contents&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#introduction&#34;&gt;Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#redux-packages-background&#34;&gt;Redux Packages Background&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#packages-and-configurations&#34;&gt;Packages and Configurations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#issue-history&#34;&gt;Issue History&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#early-attempts&#34;&gt;Early Attempts&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#migrating-to-vitest&#34;&gt;Migrating to Vitest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#initial-alpha-testing&#34;&gt;Initial Alpha Testing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#researching-better-configuration&#34;&gt;Researching Better Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#setting-up-ci-checks-for-packaging&#34;&gt;Setting Up CI Checks for Packaging&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#initial-ci-setup&#34;&gt;Initial CI Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#are-the-types-wrong&#34;&gt;Are The Types Wrong?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#packaging-updates-round-2&#34;&gt;Packaging Updates, Round 2&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#switching-build-tooling&#34;&gt;Switching Build Tooling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#umd-build-artifact-changes&#34;&gt;UMD Build Artifact Changes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#webpack-4-compat&#34;&gt;Webpack 4 Compat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#immer-10-beta&#34;&gt;Immer 10 Beta&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#typescript-declarations&#34;&gt;TypeScript Declarations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#round-2-results&#34;&gt;Round 2 Results&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#other-package-updates&#34;&gt;Other Package Updates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#updating-immers-packaging&#34;&gt;Updating Immer&#39;s Packaging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#problems-with-next-js-and-react-server-components&#34;&gt;Problems with Next.js and React Server Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#venting&#34;&gt;Venting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#final-thoughts&#34;&gt;Final Thoughts&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#where-do-things-stand-today&#34;&gt;Where Do Things Stand Today?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#lessons-and-takeaways&#34;&gt;Lessons and Takeaways&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#future-steps&#34;&gt;Future Steps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#further-information&#34;&gt;Further Information&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;For the last 8+ years, the JS ecosystem has been undergoing a slow transition towards using ES Modules (&amp;quot;ESM&amp;quot;) as the default approach for publishing and using JS code. Similar to the Python 2-&amp;gt;3 transition, this has been incredibly difficult and painful to deal with.&lt;/p&gt;

&lt;p&gt;As a package maintainer, I want to make sure that my libraries are maximally compatible and usable in the widest array of environments I can feasibly support. Unfortunately, this also means that I&#39;ve had to become familiar with the nuances and behavior quirks of a variety of different build tools and runtime environments&lt;/p&gt;

&lt;p&gt;Early this year I started working on trying to update the package formatting for the Redux family of libraries to give them &amp;quot;full ESM compatibility&amp;quot;. I &lt;em&gt;think&lt;/em&gt; I&#39;ve finally come up with a set of configurations that &lt;em&gt;seem&lt;/em&gt; to work reasonably well, but it&#39;s been a struggle.&lt;/p&gt;

&lt;p&gt;One of my biggest frustrations is that there is no single authoritative and comprehensive guide on &amp;quot;How to Publish a JS Package Correctly&amp;quot;. I&#39;ve repeatedly begged for some expert who &lt;em&gt;actually&lt;/em&gt; knows what they&#39;re doing to write and publish such a guide. Ideally, it would cover things like what file formats to include, how to configure ESM/CJS interop and &lt;code&gt;package.exports&lt;/code&gt;, dealing with TS types versions, ensuring tree shaking, checking for compatibility issues, how to properly support specific build tools and what they look for, and so on. I have found &lt;em&gt;some&lt;/em&gt; guides (which I&#39;ll link below), but nothing that quite matches the breadth and contents I&#39;ve been wishing for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This post is &lt;em&gt;not&lt;/em&gt; that &amp;quot;authoritative guide&amp;quot;.&lt;/strong&gt; It&#39;s a recap of what I&#39;ve tried, and hard-earned lessons I&#39;ve learned along the way. Based on the number of times folks have popped up and said &amp;quot;you&#39;re doing this wrong&amp;quot;, I&#39;m sure there&#39;s plenty of pieces I&#39;m still missing :) But, &lt;strong&gt;I hope this information will be useful and informative even if it&#39;s not fully comprehensive and authoritative&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There&#39;s plenty of articles out there already recapping the history of the ESM spec, the arguments and decisions that have led to the current confusion and compatibility issues, and how we got into this mess. In the interest of keeping this a somewhat manageable size, I&#39;ll try to dig up links to a few of those and list them at the end, and focus primarily on my own experience and steps throughout this process.&lt;/p&gt;

&lt;h2 id=&#34;redux-packages-background&#34;&gt;Redux Packages Background&lt;/h2&gt;

&lt;h3 id=&#34;packages-and-configurations&#34;&gt;Packages and Configurations&lt;/h3&gt;

&lt;p&gt;At the end of 2022, I maintained and published these packages as part of the Redux org:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://unpkg.com/browse/redux@4.2.1/&#34;&gt;&lt;code&gt;redux@4.2.x&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://unpkg.com/browse/react-redux@8.0.7/&#34;&gt;&lt;code&gt;react-redux@8.0.x&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://unpkg.com/browse/redux-thunk@2.4.2/&#34;&gt;&lt;code&gt;redux-thunk@2.4.x&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://unpkg.com/browse/reselect@4.1.8/&#34;&gt;&lt;code&gt;reselect@4.1.x&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://unpkg.com/browse/@reduxjs/toolkit@1.9.5/&#34;&gt;&lt;code&gt;@reduxjs/toolkit@1.9.x&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these packages had their own development history, packaging setup, and build configuration. In general:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All the packages included ESM, CJS, and UMD build artifacts (with varying combinations of embedded &lt;code&gt;process.env.NODE_ENV&lt;/code&gt; values, or pre-compiled to &lt;code&gt;&amp;quot;development&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;production&amp;quot;&lt;/code&gt; versions)&lt;/li&gt;
&lt;li&gt;All build artifacts used a &lt;code&gt;.js&lt;/code&gt; extension&lt;/li&gt;
&lt;li&gt;All the packages were being transpiled to ES5 syntax for IE11 compatibility&lt;/li&gt;
&lt;li&gt;&lt;code&gt;redux&lt;/code&gt;, &lt;code&gt;react-redux&lt;/code&gt;, &lt;code&gt;redux-thunk&lt;/code&gt;, and &lt;code&gt;reselect&lt;/code&gt; were being transpiled with Babel and bundled with Rollup. RTK was built using a custom ESBuild wrapper script that did the bundling and primary transpilation, but also used &lt;code&gt;tsc&lt;/code&gt; to lower ES2015 code to ES5.&lt;/li&gt;
&lt;li&gt;All of the packages used the &lt;code&gt;&amp;quot;main&amp;quot;&lt;/code&gt;, &lt;code&gt;&amp;quot;module&amp;quot;&lt;/code&gt;, and &lt;code&gt;&amp;quot;types&amp;quot;&lt;/code&gt; fields in &lt;code&gt;package.json&lt;/code&gt;. None of the packages used the relatively new &lt;code&gt;&amp;quot;exports&amp;quot;&lt;/code&gt; field for defining which build artifacts get loaded.&lt;/li&gt;
&lt;li&gt;Most of the packages except RTK output build artifacts to different folders by type: &lt;code&gt;dist&lt;/code&gt; for UMD, &lt;code&gt;lib&lt;/code&gt; for CJS, &lt;code&gt;es&lt;/code&gt; for ESM&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some examples from those &lt;code&gt;package.json&lt;/code&gt; files:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;redux&amp;quot;,
  &amp;quot;version&amp;quot;: &amp;quot;4.2.1&amp;quot;,
  &amp;quot;main&amp;quot;: &amp;quot;lib/redux.js&amp;quot;,
  &amp;quot;unpkg&amp;quot;: &amp;quot;dist/redux.js&amp;quot;,
  &amp;quot;module&amp;quot;: &amp;quot;es/redux.js&amp;quot;,
  &amp;quot;typings&amp;quot;: &amp;quot;./index.d.ts&amp;quot;,
  &amp;quot;files&amp;quot;: [&amp;quot;dist&amp;quot;, &amp;quot;lib&amp;quot;, &amp;quot;es&amp;quot;, &amp;quot;src&amp;quot;, &amp;quot;index.d.ts&amp;quot;]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;react-redux&amp;quot;,
  &amp;quot;version&amp;quot;: &amp;quot;8.0.5&amp;quot;,
  &amp;quot;main&amp;quot;: &amp;quot;./lib/index.js&amp;quot;,
  &amp;quot;types&amp;quot;: &amp;quot;./es/index.d.ts&amp;quot;,
  &amp;quot;unpkg&amp;quot;: &amp;quot;dist/react-redux.js&amp;quot;,
  &amp;quot;module&amp;quot;: &amp;quot;es/index.js&amp;quot;,
  &amp;quot;files&amp;quot;: [&amp;quot;dist&amp;quot;, &amp;quot;lib&amp;quot;, &amp;quot;src&amp;quot;, &amp;quot;es&amp;quot;]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;@reduxjs/toolkit&amp;quot;,
  &amp;quot;version&amp;quot;: &amp;quot;1.9.5&amp;quot;,
  &amp;quot;main&amp;quot;: &amp;quot;dist/index.js&amp;quot;,
  &amp;quot;module&amp;quot;: &amp;quot;dist/redux-toolkit.esm.js&amp;quot;,
  &amp;quot;unpkg&amp;quot;: &amp;quot;dist/redux-toolkit.umd.min.js&amp;quot;,
  &amp;quot;types&amp;quot;: &amp;quot;dist/index.d.ts&amp;quot;,
  &amp;quot;files&amp;quot;: [
    &amp;quot;dist/**/*.js&amp;quot;,
    &amp;quot;dist/**/*.js.map&amp;quot;,
    &amp;quot;dist/**/*.d.ts&amp;quot;,
    &amp;quot;dist/**/package.json&amp;quot;,
    &amp;quot;src/&amp;quot;,
    &amp;quot;query&amp;quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;RTK&#39;s setup was more complicated, because it has 3 separate entry points: &lt;code&gt;@reduxjs/toolkit&lt;/code&gt;, &lt;code&gt;@reduxjs/toolkit/query&lt;/code&gt;, and &lt;code&gt;@reduxjs/toolkit/query/react&lt;/code&gt;. Note that RTK&#39;s &lt;code&gt;package.json&lt;/code&gt; didn&#39;t list the two RTKQ entry points. Instead, there was an actual &lt;code&gt;/query&lt;/code&gt; folder in the published package, with &lt;code&gt;/query/package.json&lt;/code&gt; and &lt;code&gt;/query/react/package.json&lt;/code&gt; files that in turn pointed over to the right artifacts in the &lt;code&gt;dist&lt;/code&gt; folder. (This setup was the result of considerable experimentation, aka &amp;quot;it seems to work with Webpack and a couple other tools I think???&amp;quot;).&lt;/p&gt;

&lt;p&gt;While not directly relevant for the rest of the story, I&#39;d like to give a shout out to two highly useful tools that I use as part of the publishing process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/release-it/release-it&#34;&gt;&lt;code&gt;release-it&lt;/code&gt;&lt;/a&gt;: automates the actual steps for publishing to NPM, including Git tagging and pushing&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.npmjs.com/package/yalc&#34;&gt;&lt;code&gt;yalc&lt;/code&gt;&lt;/a&gt;: lets you do a full local &amp;quot;publish&amp;quot; of a package so that you can test out installing it into example projects. Avoids issues with symlinks (ie &lt;code&gt;npm link&lt;/code&gt;), and tests out the real build and publish steps.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;issue-history&#34;&gt;Issue History&lt;/h3&gt;

&lt;p&gt;In mid-2021, we received an issue reporting that &lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/issues/1396&#34;&gt;RTK could not be loaded properly in &lt;em&gt;both&lt;/em&gt; client and server code simultaneously&lt;/a&gt;. In early 2022, a similar issue reported that &lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/issues/1960&#34;&gt;RTK could not be correctly imported in a &lt;code&gt;.mjs&lt;/code&gt; ESM file&lt;/a&gt;, due to use of &lt;code&gt;&amp;quot;module&amp;quot;&lt;/code&gt; but no &lt;code&gt;&amp;quot;exports&amp;quot;&lt;/code&gt; field in &lt;code&gt;package.json&lt;/code&gt;. Finally, another issue noted that &lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/issues/2485&#34;&gt;RTK didn&#39;t work with TypeScript&#39;s new &lt;code&gt;moduleResolution: &amp;quot;node16&amp;quot;&lt;/code&gt; option&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;d previously asked around about the implications of adding &lt;code&gt;&amp;quot;exports&amp;quot;&lt;/code&gt; to a package, and I&#39;d been told that &amp;quot;this qualifies as a breaking change&amp;quot;. That meant that I couldn&#39;t begin to consider doing it until the next major release for each of the packages. But, I had no idea when we&#39;d get around to publishing majors. Redux 4.0 came out all the way back in 2018, and RTK 1.0 in late 2019. React-Redux 8.0 was more recent, in mid-2022.&lt;/p&gt;

&lt;p&gt;The Redux core had actually been converted to TS in 2019, but we&#39;d never shipped it. 4.x and its hand-written typedefs worked, and we had concerns about potential ecosystem churn from shipping a 5.0 major. We also had plenty of feature work to do with RTK.&lt;/p&gt;

&lt;p&gt;We shipped RTK 1.9 in November 2022. After taking a couple month break, I finally sat down to start seriously working on trying to modernize our packages.&lt;/p&gt;

&lt;h2 id=&#34;early-attempts&#34;&gt;Early Attempts&lt;/h2&gt;

&lt;p&gt;I&#39;d been stockpiling a list of tabs and articles around &amp;quot;publishing modern JS&amp;quot;, ESM, and ESM/CJS interop for the last few years, &lt;em&gt;knowing&lt;/em&gt; that this day would come eventually. (At last check, I had roughly 175 articles in that list!).&lt;/p&gt;

&lt;p&gt;I reviewed several of those articles to figure out my initial steps. From what I read, I concluded that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I &lt;em&gt;needed&lt;/em&gt; to add &lt;code&gt;&amp;quot;type&amp;quot;: &amp;quot;module&amp;quot;&lt;/code&gt; to my &lt;code&gt;package.json&lt;/code&gt; files, in order for Node and bundlers to detect the package as containing ESM files&lt;/li&gt;
&lt;li&gt;I also needed to add the &lt;code&gt;&amp;quot;exports&amp;quot;&lt;/code&gt; key to &lt;code&gt;package.json&lt;/code&gt;, and add keys inside that listed the possible entry points and what build artifacts to use when imported in different environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&#39;d seen mentions of using &lt;code&gt;.mjs&lt;/code&gt; as a file extension to force Node to recognize a given file as being an ES Module. To be honest, I felt that looked ugly and ridiculous, and I did &lt;em&gt;not&lt;/em&gt; want to use that extension at all.&lt;/p&gt;

&lt;p&gt;My first attempt was &lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/pull/3095&#34;&gt;RTK PR #3095: Migrate the RTK package to be full ESM&lt;/a&gt;. Per my PR description, it contained these changes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This PR attempts to convert the RTK package from its existing &amp;quot;contains ESM and CJS modules, but not &lt;em&gt;fully&lt;/em&gt; ESM&amp;quot;, to be fully ESM with &lt;code&gt;{type: &amp;quot;module&amp;quot;}&lt;/code&gt; and still support CJS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;BREAKING&lt;/strong&gt;: Sets the main RTK &lt;code&gt;package.json&lt;/code&gt; file to be &lt;code&gt;{type: &amp;quot;module&amp;quot;}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BREAKING&lt;/strong&gt;: Updates all entry point &lt;code&gt;package.json&lt;/code&gt; files to use &lt;code&gt;exports&lt;/code&gt; to point to the types, ESM file, and CJS file

&lt;ul&gt;
&lt;li&gt;I still have &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;module&lt;/code&gt; in there because WHO KNOWS WHETHER THOSE STILL END UP GETTING USED BY SOME TOOLS OR NOT 🤷‍♂️&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Updates the build script:

&lt;ul&gt;
&lt;li&gt;Fixed ESM compat on execution by replacing use of &lt;code&gt;__dirname&lt;/code&gt; and fixing the Terser import&lt;/li&gt;
&lt;li&gt;Switched all build targets to be &lt;code&gt;&amp;quot;esnext&amp;quot;&lt;/code&gt;, to ensure the output is untouched other than TS transpilation&lt;/li&gt;
&lt;li&gt;Moved all CJS build artifacts to be nested a level deeper in each entry point in a &lt;code&gt;./cjs/&lt;/code&gt; folder, ie, &lt;code&gt;./dist/query/cjs/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Added &lt;code&gt;{type: &amp;quot;commonjs&amp;quot;}&lt;/code&gt; package files to those folders&lt;/li&gt;
&lt;li&gt;Turned off the UMD build artifacts for now&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;The resulting &lt;code&gt;package.json&lt;/code&gt; looked like this:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;@reduxjs/toolkit&amp;quot;,
  &amp;quot;version&amp;quot;: &amp;quot;2.0.0-alpha.1&amp;quot;,
  &amp;quot;type&amp;quot;: &amp;quot;module&amp;quot;,
  &amp;quot;module&amp;quot;: &amp;quot;dist/redux-toolkit.modern.js&amp;quot;,
  &amp;quot;main&amp;quot;: &amp;quot;dist/cjs/index.js&amp;quot;,
  &amp;quot;types&amp;quot;: &amp;quot;dist/index.d.ts&amp;quot;,
  &amp;quot;exports&amp;quot;: {
    &amp;quot;./package.json&amp;quot;: &amp;quot;./package.json&amp;quot;,
    &amp;quot;.&amp;quot;: {
      &amp;quot;types&amp;quot;: &amp;quot;./dist/index.d.ts&amp;quot;,
      &amp;quot;import&amp;quot;: &amp;quot;./dist/redux-toolkit.modern.js&amp;quot;,
      &amp;quot;default&amp;quot;: &amp;quot;./dist/cjs/index.js&amp;quot;
    },
    &amp;quot;./query&amp;quot;: {
      &amp;quot;types&amp;quot;: &amp;quot;./dist/query/index.d.ts&amp;quot;,
      &amp;quot;import&amp;quot;: &amp;quot;./dist/query/rtk-query.modern.js&amp;quot;,
      &amp;quot;default&amp;quot;: &amp;quot;./dist/query/cjs/index.js&amp;quot;
    },
    &amp;quot;./query/react&amp;quot;: {
      &amp;quot;types&amp;quot;: &amp;quot;./dist/query/react/index.d.ts&amp;quot;,
      &amp;quot;import&amp;quot;: &amp;quot;./dist/query/react/rtk-query-react.modern.js&amp;quot;,
      &amp;quot;default&amp;quot;: &amp;quot;./dist/query/react/cjs/index.js&amp;quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I did try testing out local builds in Vite, CRA4/5, Next, and Node, as well as running the &lt;a href=&#34;https://publint.dev/&#34;&gt;&lt;code&gt;publint&lt;/code&gt;&lt;/a&gt; tool. Things &lt;em&gt;seemed&lt;/em&gt; to mostly work locally, so I put up the PR to see what would happen with CI&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AND EVERYTHING EXPLODED!!!! 💣💣💣&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I spent a few more hours fiddling with things, and reported my findings:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Well. The good news is I think the &lt;em&gt;runtime&lt;/em&gt; code works.&lt;/p&gt;

&lt;p&gt;Bad news is Jest is being a pain. In particular, something about the way it&#39;s importing &lt;code&gt;redux-thunk&lt;/code&gt; makes the default import an object like &lt;code&gt;{default}&lt;/code&gt;, which is not a middleware function, and thus the tests explode when we try to create a store.&lt;/p&gt;

&lt;p&gt;I spent the last couple hours hacking around with the thunk exports and republishing it locally. Switching the thunk package over to &lt;em&gt;not&lt;/em&gt; having a default export at all sorta helped, but now something about the &amp;quot;no dev middleware in prod&amp;quot; test is failing.&lt;/p&gt;

&lt;p&gt;So, close, but can&#39;t even build this branch yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;edit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;where I left off yesterday was that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;redux-thunk&lt;/code&gt; has a default export, and Jest was now choking on that&lt;/li&gt;
&lt;li&gt;I published &lt;code&gt;redux-thunk@3.0.0-alpha&lt;/code&gt; that tried to convert &lt;em&gt;it&lt;/em&gt; to ESM, but still had a default export included. That helped build with Next, but not our local Jest tests&lt;/li&gt;
&lt;li&gt;I then did a local-only publish of &lt;code&gt;redux-thunk&lt;/code&gt; that dropped the default export and only had named exports. That actually seemed to help, but one of our RTK tests that asserts &lt;code&gt;NODE_ENV=production&lt;/code&gt; behavior for &lt;code&gt;getDefaultMiddleware&lt;/code&gt; was breaking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some folks in Reactiflux suggested that it might be worth investigating a switch to Vitest. I&#39;d prefer not to do that if possible, on the grounds that migrating to a different test runner is not my priority or something I want to spend time on. On the other hand, it could also be something that would be beneficial in general and for this specific problem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&#34;migrating-to-vitest&#34;&gt;Migrating to Vitest&lt;/h3&gt;

&lt;p&gt;I really didn&#39;t &lt;em&gt;want&lt;/em&gt; to burn time trying to migrate our entire test setup from Jest to Vitest. But, I&#39;d heard plenty of positive comments about Vitest, including that it ran significantly faster and had better ESM support.&lt;/p&gt;

&lt;p&gt;A couple days later I decided to give it a shot. To my pleasant surprise, the conversion was fairly straightforward.&lt;/p&gt;

&lt;p&gt;I ended up with &lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/pull/3102&#34;&gt;RTK PR #3102: Migrate RTK test suite from Jest to Vitest&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The main test setup made sense, and the &lt;code&gt;jest.fn()&lt;/code&gt; -&amp;gt; &lt;code&gt;vi.fn()&lt;/code&gt; swaps were straightforward. The biggest pain point I ran into was where we tried to mock the &lt;code&gt;redux&lt;/code&gt; package to assert that &lt;code&gt;configureStore&lt;/code&gt; was calling through to the core library. Had to do a bunch of fiddling with &lt;code&gt;vi.mock()&lt;/code&gt; until something finally seemed to work. On the other hand, timer behavior seemed to work more consistently.&lt;/p&gt;

&lt;p&gt;As part of this process, I found myself also needing to convert other auxiliary files in the repo to ESM syntax, such as Jest config files and build scripts with a &lt;code&gt;.js&lt;/code&gt; extension.&lt;/p&gt;

&lt;p&gt;I was able to get that PR passing, and merge it a couple days later.&lt;/p&gt;

&lt;h3 id=&#34;initial-alpha-testing&#34;&gt;Initial Alpha Testing&lt;/h3&gt;

&lt;p&gt;I published &lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/releases/tag/v2.0.0-alpha.1&#34;&gt;@reduxjs/toolkit@2.0.0-alpha.1&lt;/a&gt; on January 21. This included the RTK packaging changes, as well as a similar change to &lt;code&gt;redux-thunk&lt;/code&gt;, and modernized the build artifacts to no longer transpile any JS syntax and drop IE11 compat.&lt;/p&gt;

&lt;p&gt;Of course, this did not work as well as I&#39;d hoped :)&lt;/p&gt;

&lt;p&gt;Mateusz Burzyński ( &lt;a href=&#34;https://twitter.com/andaristrake&#34;&gt;@andaristrake&lt;/a&gt; ) maintains several libraries, including Emotion and Preconstruct, and spends much of his time working on the TypeScript compiler for fun. He&#39;s an expert on many of the intricate nuances of packaging formatting.&lt;/p&gt;

&lt;p&gt;When I announced &lt;code&gt;alpha.2&lt;/code&gt; on Twitter, &lt;a href=&#34;https://twitter.com/AndaristRake/status/1625781199724576768&#34;&gt;Mateusz replied with several suggestions for tweaks&lt;/a&gt; (looking at both RTK 2.0 and Redux core 5.0 alphas):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;no idea what &lt;code&gt;dist/es/redux.mjs&lt;/code&gt; is for now if it&#39;s not even in the exports map&lt;/p&gt;

&lt;p&gt;by using the types condition like this TS might always assume that this is a module, even if loaded/required from CJS target~. Since you don&#39;t have a default export... that&#39;s &lt;em&gt;probably&lt;/em&gt; fine&lt;/p&gt;

&lt;p&gt;I would include the module condition and point to the ./dist/es/index.js with it, this will allow the package to be only loaded once by bundlers, despite the consuming file&#39;s format (cjs vs esm)&lt;/p&gt;

&lt;p&gt;get rid of process.env.NODE_ENV in your dist files, use development/production conditions to accomplish this stuff (probably best to make production the default and the development stuff an opt-in)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I saved those as an issue for reference.&lt;/p&gt;

&lt;p&gt;Shortly thereafter, we received a couple of new issue reports back-to-back complaining of problems with the config in &lt;code&gt;alpha.1/2&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/issues/3202&#34;&gt;RTK #3202: Cannot resolve types when moduleResolution is set to node16&lt;/a&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;When importing anything from &lt;code&gt;@reduxjs/toolkit@2.0.0-alpha.2&lt;/code&gt;, typescript cannot resolve types when &lt;code&gt;tsconfig.json&#39;s&lt;/code&gt; &lt;code&gt;moduleResolution&lt;/code&gt; is set to &lt;code&gt;&amp;quot;node16&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;nodenext&amp;quot;&lt;/code&gt;.
I found that adding the extension &lt;code&gt;.js&lt;/code&gt; to the declaration imports resolved the issue.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/issues/3208&#34;&gt;RTK #3208: Invalid exports config for CJS consumption w/ Node&lt;/a&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The current config in the Alpha does not allow for consumption of the CJS bundle in modern version of Node/any tool that follows Node&#39;s module resolution spec, as it uses &lt;code&gt;.js&lt;/code&gt; to refer to a CJS module despite the package setting &lt;code&gt;&amp;quot;type&amp;quot;: &amp;quot;module&amp;quot;&lt;/code&gt;. If &lt;code&gt;&amp;quot;type&amp;quot;: &amp;quot;module&amp;quot;&lt;/code&gt; is set, &lt;code&gt;.cjs&lt;/code&gt; is necessary in &lt;code&gt;&amp;quot;exports&amp;quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Some bundlers do work around this and are more forgiving (whether or not that&#39;s a good thing is something else entirely), but this config will not work in Node and/or any environments that follow its resolution mechanism.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I was... &lt;em&gt;not&lt;/em&gt; a happy camper:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I do honestly appreciate you filing the issue, but I am also legitimately getting angry at how messed up this whole situation is :(&lt;/p&gt;

&lt;p&gt;I want to do right by my users and support the variety of build tools and environments I expect they&#39;ll be using for their apps.&lt;/p&gt;

&lt;p&gt;But I can&#39;t do that if &lt;strong&gt;every single article and person is giving me contradictory instructions on what I&#39;m supposed to do :(&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Clearly this was going to take a lot of effort to figure out what was going on and catch possible errors.&lt;/p&gt;

&lt;h2 id=&#34;researching-better-configuration&#34;&gt;Researching Better Configuration&lt;/h2&gt;

&lt;p&gt;Right at the same time, &lt;a href=&#34;https://twitter.com/devongovett/status/1629161014812897282&#34;&gt;Devon Govett tweeted about improving Node+ESM support in a React-Aria package update&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I replied noting I was working on some similar efforts, and tagged Mateusz. Shortly after that I saw the issues get filed, linked and griped about them, and Mateusz again suggested removing &lt;code&gt;type: &amp;quot;module&amp;quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I was feeling frustrated and begged him to publish a full blog post that would give details on his recommendations. Instead, he suggested we do a phone call and talk through things directly.&lt;/p&gt;

&lt;p&gt;On February 27, Mateusz and I hopped onto a call along with Nathan Bierema (Redux DevTools maintainer). I saved the discussion notes in a gist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/markerikson/42d55b0fd970449fc5d84263f4775cbd#file-rtk-esm-ts-notes-2023-02-27-md&#34;&gt;&lt;strong&gt;RTK ESM/TS Discussion: Mateusz Burzyński&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mateusz threw out a lot of thoughts around how ESM and CJS &lt;em&gt;can&lt;/em&gt; get used, and questioned whether it even entirely makes sense to ship ESM at all. The information was useful in general, but it left me still feeling pretty confused about next steps.&lt;/p&gt;

&lt;p&gt;Somewhere in that Twitter discussion, I got in touch with &lt;a href=&#34;https://twitter.com/atcb&#34;&gt;Andrew Branch (&lt;code&gt;@atcb&lt;/code&gt;)&lt;/a&gt;, a TypeScript team member who had implemented the new &lt;code&gt;moduleResolution: &amp;quot;bundler&amp;quot;&lt;/code&gt; option for TS, and has been doing work on JS/TS ecosystem module behavior as preparation for writing. We set up a call on February 28.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/markerikson/42d55b0fd970449fc5d84263f4775cbd#file-tk-esm-ts-notes-2023-02-28-md&#34;&gt;&lt;strong&gt;RTK ESM/TS Discussion: Andrew Branch&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Andrew gave me a rundown of how ESM works, how TS treats ESM and module import paths, and how Node and other tools determine if a file is actually ESM.&lt;/p&gt;

&lt;p&gt;The TL;DR of that last part is roughly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you add &lt;code&gt;type: &amp;quot;module&amp;quot;&lt;/code&gt;, every file with a &lt;code&gt;.js&lt;/code&gt; extension gets interpreted as ESM, period. &lt;code&gt;.cjs&lt;/code&gt; files will be interpreted as CommonJS.&lt;/li&gt;
&lt;li&gt;Alternately, if you &lt;em&gt;don&#39;t&lt;/em&gt; have &lt;code&gt;type: &amp;quot;module&amp;quot;&lt;/code&gt;, &lt;code&gt;.js&lt;/code&gt; files are treated as CommonJS. You can use &lt;code&gt;.mjs&lt;/code&gt; to mark individual files as ESM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There was also some discussion of whether or not we should be pre-bundling our TS typedefs or leaving them as individual &lt;code&gt;someSourceFile.d.ts&lt;/code&gt; files in the published package.&lt;/p&gt;

&lt;h2 id=&#34;setting-up-ci-checks-for-packaging&#34;&gt;Setting Up CI Checks for Packaging&lt;/h2&gt;

&lt;h3 id=&#34;initial-ci-setup&#34;&gt;Initial CI Setup&lt;/h3&gt;

&lt;p&gt;I&#39;d suspected for a long time that I was going to end up needing to put together some kind of battery of example applications, each using different build tooling, to catch possible errors in packaging during PR CI checks.&lt;/p&gt;

&lt;p&gt;After the &lt;code&gt;alpha.2&lt;/code&gt; issue reports, I reluctantly concluded I really needed to spend time setting up those CI checks before I did any more work on the actual package configurations.&lt;/p&gt;

&lt;p&gt;As part of my initial testing, I had locally created a small example app that exercised all of RTK&#39;s entry points. It had a counter to exercise &lt;code&gt;configureStore&lt;/code&gt; and &lt;code&gt;createSlice&lt;/code&gt; from the core, a UI-agnostic RTKQ &lt;code&gt;createApi&lt;/code&gt; endpoint, and a React-specific RTKQ &lt;code&gt;createApi&lt;/code&gt; endpoint. I&#39;d pasted that into several different project setups.&lt;/p&gt;

&lt;p&gt;We already had our CI set up to pre-build a tarball containing the package contents from the current PR, and were using that to run our unit tests against the PR package version instead of our source code. I decided to try expanding on that to test these different apps against that PR build as well.&lt;/p&gt;

&lt;p&gt;I copied the first couple example projects into a new &lt;code&gt;$REPO/examples/publish-ci/&lt;/code&gt; folder, and updated the GH Action workflow to matrix the folder names inside of &lt;code&gt;/publish-ci/&lt;/code&gt;, install the PR build into each example, then build+test it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/pull/3213&#34;&gt;RTK PR #3213: Test published artifacts in CI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also wrote a small Playwright test that would check the page contents to verify it could change the counter, and that both API endpoints had fetched the right mock data, in order to ensure that the apps actually &lt;em&gt;ran&lt;/em&gt; correctly.&lt;/p&gt;

&lt;p&gt;I actually targeted the PR against 1.9.x on our &lt;code&gt;master&lt;/code&gt; branch, to see how things worked with the existing package setup first.&lt;/p&gt;

&lt;p&gt;I eventually ended up with example apps that covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CRA 4 (with Webpack 4)&lt;/li&gt;
&lt;li&gt;CRA 5 (with Webpack 5)&lt;/li&gt;
&lt;li&gt;Next.js (with Webpack 5)&lt;/li&gt;
&lt;li&gt;Vite 4&lt;/li&gt;
&lt;li&gt;Node in both CJS and ESM modes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There were &lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/issues/3365&#34;&gt;plenty of other build tool combinations that probably ought to be checked&lt;/a&gt;, but this is a good start.&lt;/p&gt;

&lt;h3 id=&#34;are-the-types-wrong&#34;&gt;Are The Types Wrong?&lt;/h3&gt;

&lt;p&gt;Somewhere in this process, I had discovered that Andrew Branch had created a tool called &lt;a href=&#34;https://arethetypeswrong.github.io&#34;&gt;Are The Types Wrong&lt;/a&gt;. It&#39;s a website that lets you pick a published NPM package version, or upload a &lt;code&gt;.tgz&lt;/code&gt; file, and analyzes the package exports to report how TypeScript interprets the configuration and whether the JS files and TS typedefs match up correctly. It then shows all your detected entry points, and reports details on any mismatches and errors.&lt;/p&gt;

&lt;p&gt;Here&#39;s an example of the report for RTK &lt;code&gt;2.0.0-alpha.2&lt;/code&gt; ( &lt;a href=&#34;https://arethetypeswrong.github.io&#34;&gt;https://arethetypeswrong.github.io&lt;/a&gt; ):&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.isquaredsoftware.com/images/2023-06-esm-modernization/attw-rtk-2.0-alpha.2.png&#34; alt=&#34;Are The Types Wrong - RTK 2.0-alpha.2 results&#34; /&gt;&lt;/p&gt;

&lt;p&gt;You can see that it detected all of RTK&#39;s entry points, and that most of the entry point + &lt;code&gt;moduleResolution&lt;/code&gt; combinations look okay. But, &lt;code&gt;moduleResolution: &amp;quot;node16&amp;quot;&lt;/code&gt; + some CJS environment apparently has multiple issues.&lt;/p&gt;

&lt;p&gt;I really wanted to use this analysis in RTK&#39;s CI to help verify that any future PR changes would actually work correctly. I looked at &lt;a href=&#34;https://github.com/arethetypeswrong/arethetypeswrong.github.io&#34;&gt;the &lt;code&gt;attw&lt;/code&gt; repo&lt;/a&gt;, and noted that Andrew had split it into &lt;code&gt;core&lt;/code&gt; and &lt;code&gt;website&lt;/code&gt; packages. But, the core logic wasn&#39;t yet published as a package.&lt;/p&gt;

&lt;p&gt;I initially tried setting up a CI task that would clone the &lt;code&gt;attw&lt;/code&gt; repo, and let me write a command-line script that would import the core logic and analyze the PR build artifact. That technically worked, but fortunately I was able to convince Andrew to publish the logic as an actual &lt;code&gt;@arethetypeswrong/core&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;From there, I put together &lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/blob/f31ff77ad01f6cdbdbbd4a701718ac8445e34b91/examples/publish-ci/are-the-types-wrong/main.tsx&#34;&gt;a CLI script that ran the core &lt;code&gt;attw&lt;/code&gt; logic, collected the reports, and wrote it out as a console table&lt;/a&gt; to match the display on the website. I did this using the &lt;code&gt;ink&lt;/code&gt; React CLI renderer (and probably spent a bit too much time fiddling with rendering tables in the console). The results ended up pretty good:&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://blog.isquaredsoftware.com/images/2023-06-esm-modernization/attw-cli.png&#34; alt=&#34;Are The Types Wrong CLI output&#34; /&gt;&lt;/p&gt;

&lt;p&gt;I then configured RTK&#39;s CI to call that as another check alongside building the example apps.&lt;/p&gt;

&lt;p&gt;There was &lt;a href=&#34;https://github.com/arethetypeswrong/arethetypeswrong.github.io/issues/15&#34;&gt;an existing thread asking for &lt;code&gt;attw&lt;/code&gt; to add a CLI&lt;/a&gt;, so I offered mine up as a potential starting point. (Someone else &lt;a href=&#34;https://github.com/arethetypeswrong/arethetypeswrong.github.io/pull/26&#34;&gt;later filed a PR to add a CLI&lt;/a&gt;. That CLI has now been &lt;a href=&#34;https://github.com/arethetypeswrong/arethetypeswrong.github.io/tree/main/packages/cli&#34;&gt;published officially&lt;/a&gt;, and I need to get around to switching over to using that in CI instead of my homegrown script.&lt;/p&gt;

&lt;h2 id=&#34;packaging-updates-round-2&#34;&gt;Packaging Updates, Round 2&lt;/h2&gt;

&lt;p&gt;I decided it was best to try updating the smaller packages that RTK depends on first.&lt;/p&gt;

&lt;p&gt;I&#39;d already had to publish a &lt;code&gt;3.0-alpha.0&lt;/code&gt; for &lt;code&gt;redux-thunk&lt;/code&gt; to alter its behavior. I decided I&#39;d switch over and try making further updates with that.&lt;/p&gt;

&lt;h3 id=&#34;switching-build-tooling&#34;&gt;Switching Build Tooling&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;redux-thunk&lt;/code&gt; is a single tiny source file about 20 lines long (plus some additional TS types). That made it a good starting point to mess with changing packaging.&lt;/p&gt;

&lt;p&gt;I noted that it was still using Babel+Rollup for the build step. I decided I&#39;d try using ESBuild instead. But, how should I use that?&lt;/p&gt;

&lt;p&gt;We already had a custom ESBuild wrapper script over in RTK. I briefly considered copy-pasting that over to the &lt;code&gt;redux-thunk&lt;/code&gt; repo, but decided it would be overkill.&lt;/p&gt;

&lt;p&gt;I&#39;d done some previous searching for other ESBuild wrappers. I did some more looking and decided to give &lt;a href=&#34;https://github.com/egoist/tsup&#34;&gt;https://github.com/egoist/tsup&lt;/a&gt; a shot.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tsup&lt;/code&gt; actually worked out pretty well! In a couple hours I had a simple &lt;code&gt;tsup.config.ts&lt;/code&gt; file that generated the two artifacts I wanted. In this case the thunk code had no dev/prod conditional checks, so I kept it really simple - just a single ESM and CJS file apiece.&lt;/p&gt;

&lt;p&gt;I also removed &lt;code&gt;type: &amp;quot;module&amp;quot;&lt;/code&gt;, and switched to using &lt;code&gt;.mjs&lt;/code&gt; and &lt;code&gt;.cjs&lt;/code&gt; for the artifacts to force ESM or CJS appropriately.&lt;/p&gt;

&lt;p&gt;I updated the thunk &lt;code&gt;package.json&lt;/code&gt; file to use those:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;redux-thunk&amp;quot;,
  &amp;quot;version&amp;quot;: &amp;quot;3.0.0-alpha.1&amp;quot;,
  &amp;quot;main&amp;quot;: &amp;quot;dist/cjs/index.cjs&amp;quot;,
  &amp;quot;module&amp;quot;: &amp;quot;dist/index.mjs&amp;quot;,
  &amp;quot;types&amp;quot;: &amp;quot;dist/index.d.ts&amp;quot;,
  &amp;quot;exports&amp;quot;: {
    &amp;quot;./package.json&amp;quot;: &amp;quot;./package.json&amp;quot;,
    &amp;quot;.&amp;quot;: {
      &amp;quot;types&amp;quot;: &amp;quot;./dist/index.d.ts&amp;quot;,
      &amp;quot;import&amp;quot;: &amp;quot;./dist/index.mjs&amp;quot;,
      &amp;quot;default&amp;quot;: &amp;quot;./dist/cjs/index.cjs&amp;quot;
    },
    &amp;quot;./extend-redux&amp;quot;: {
      &amp;quot;types&amp;quot;: &amp;quot;./extend-redux.d.ts&amp;quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Meanwhile, I ended up doing all the same Jest-&amp;gt;Vitest conversion as the RTK repo.&lt;/p&gt;

&lt;h3 id=&#34;umd-build-artifact-changes&#34;&gt;UMD Build Artifact Changes&lt;/h3&gt;

&lt;p&gt;I also spent a bunch of time debating whether it was worth keeping UMD files or not. &lt;code&gt;redux-thunk&lt;/code&gt; &lt;em&gt;had&lt;/em&gt; shipped with a UMD bundle, primarily for use as a script tag (which I assumed was mostly being done in CodePens or similar examples).&lt;/p&gt;

&lt;p&gt;I have &lt;em&gt;repeatedly&lt;/em&gt; &lt;a href=&#34;https://twitter.com/acemarke/status/1411777215042363396&#34;&gt;asked about&lt;/a&gt; &lt;a href=&#34;https://twitter.com/acemarke/status/1619467229258727424&#34;&gt;whether to&lt;/a&gt; &lt;a href=&#34;https://twitter.com/acemarke/status/1614338592939163649&#34;&gt;keep publishing&lt;/a&gt; &lt;a href=&#34;https://twitter.com/acemarke/status/1642561150339411968&#34;&gt;UMD builds&lt;/a&gt; over the last couple years.&lt;/p&gt;

&lt;p&gt;The closest I got to actual advice and answers were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/acemarke/status/1411803139716665344&#34;&gt;Fred K Schott&lt;/a&gt;: &amp;quot;HTML examples and code editors aren&#39;t even reasons to use UMD anymore, on their own. Ex: @CodePen ships with a built-in Skypack integration&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/marvinhagemeist/status/1642573135701504002&#34;&gt;Marvin Hagemeister&lt;/a&gt;: &amp;quot;I think it&#39;s fine to skip UMD. All bundlers can consume ESM, and with sites like &lt;a href=&#34;https://esm.sh&#34;&gt;https://esm.sh&lt;/a&gt; that can be easily used in the browser.&amp;quot;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, I decided it was &lt;a href=&#34;https://twitter.com/acemarke/status/1642570701772058624&#34;&gt;finally time to drop UMD builds from the Redux packages&lt;/a&gt; :)&lt;/p&gt;

&lt;p&gt;Later, I decided the best replacement for UMD was to include another ESM-format build artifact that was pre-compiled to production mode and no longer had &lt;code&gt;process.env.NODE_ENV&lt;/code&gt; references, so that it could be safely loaded in a browser. That way people could use it as a &lt;code&gt;&amp;lt;script type=&amp;quot;module&amp;quot;&amp;gt;&lt;/code&gt; and load it from the package as hosted by Unpkg or a similar CDN.&lt;/p&gt;

&lt;p&gt;(I asked for feedback on use cases for keeping UMD as part of our alpha/beta release notes and have not yet received a single comment... but we all know that almost no one gives feedback on pre-release versions anyway 🤷‍♂️)&lt;/p&gt;

&lt;h3 id=&#34;webpack-4-compat&#34;&gt;Webpack 4 Compat&lt;/h3&gt;

&lt;p&gt;In early March, I saw a tweet from Dominik Dorfmeister (maintainer of React Query) noting that &lt;a href=&#34;https://twitter.com/TkDodo/status/1632854140320710656&#34;&gt;Webpack 4 still has more downloads than Webpack 5&lt;/a&gt;. This is mostly due to existing projects that use Webpack internally, such as CRA 4, Storybook 6, Expo&#39;s web target, etc, as well as general ecosystem usage.&lt;/p&gt;

&lt;p&gt;Unfortunately, &lt;a href=&#34;https://github.com/webpack/webpack/issues/9509&#34;&gt;Webpack 4 does not support the package &lt;code&gt;&amp;quot;exports&amp;quot;&lt;/code&gt; field&lt;/a&gt;, and it also &lt;a href=&#34;https://github.com/webpack/webpack/issues/10227&#34;&gt;cannot properly parse code with optional chaining syntax&lt;/a&gt;. Finally, I also figured out that &lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/pull/3318#issuecomment-1493645057&#34;&gt;it doesn&#39;t like having a &lt;code&gt;.mjs&lt;/code&gt; file in the &lt;code&gt;&amp;quot;main&amp;quot;&lt;/code&gt; field&lt;/a&gt; either, and needs a &lt;code&gt;.js&lt;/code&gt; extension instead.&lt;/p&gt;

&lt;p&gt;Part of my goal for these major versions was to stop transpiling away &lt;em&gt;any&lt;/em&gt; of our JS syntax, only transpile TS types, and only ship fully modern JS. However, I also care about giving our users a good out-of-the-box experience. It was clear that trying to only ship modernized code would cause problems for anyone still on Webpack 4.&lt;/p&gt;

&lt;p&gt;I grudgingly decided that I would include an additional artifact specifically for Webpack 4 compat: ESM module format, transpiled to ES2017 syntax, and using a &lt;code&gt;.js&lt;/code&gt; extension, and point to that in the &lt;code&gt;&amp;quot;main&amp;quot;&lt;/code&gt; field.&lt;/p&gt;

&lt;h3 id=&#34;immer-10-beta&#34;&gt;Immer 10 Beta&lt;/h3&gt;

&lt;p&gt;Michel Weststrate, author of the &lt;a href=&#34;https://immerjs.github.io/immer/&#34;&gt;Immer immutable update library&lt;/a&gt;, had said back in January that &lt;a href=&#34;https://github.com/immerjs/immer/issues/1015#issuecomment-1404860676&#34;&gt;he planned to work on Immer 10 in the spring&lt;/a&gt;. The major planned updates were around performance and dropping legacy ES5 compat. But, Immer also had some similar packaging issues, including use of both default and named exports. Immer had shipped the addition of &lt;code&gt;&amp;quot;exports&amp;quot;&lt;/code&gt; in &lt;a href=&#34;https://github.com/immerjs/immer/issues/937&#34;&gt;a 9.x patch release&lt;/a&gt;, only for it to break many users. The change was tweaked and half-reverted immediately, leaving Immer with an odd package config.&lt;/p&gt;

&lt;p&gt;I&#39;d left a comment in January noting &lt;a href=&#34;https://github.com/immerjs/immer/issues/937#issuecomment-1386385087&#34;&gt;how I&#39;d run into issues with packages having both default and named exports&lt;/a&gt;, so Michel opted to drop the default export in 10.0.&lt;/p&gt;

&lt;p&gt;Once Immer 10 came out in beta, I updated the RTK 2.0 branch to depend on that.&lt;/p&gt;

&lt;h3 id=&#34;typescript-declarations&#34;&gt;TypeScript Declarations&lt;/h3&gt;

&lt;p&gt;Redux 4.x ships with a hand-written TS typedefs file. RTK 1.x has individual TS typedefs files per-source-file, generated from sources.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tsup&lt;/code&gt; has a &lt;code&gt;dts: true&lt;/code&gt; option that will call &lt;code&gt;tsc&lt;/code&gt; to generate typedefs, &lt;em&gt;and&lt;/em&gt; bundle them together into a single file. That worked fine for Redux, but I ran into some kind of issue doing that for RTK. I eventually settled for sticking with individual per-source typedefs files in RTK.&lt;/p&gt;

&lt;p&gt;At this point I had package configurations that passed the &lt;code&gt;are-the-types-wrong&lt;/code&gt; checks, with one exception: a &lt;code&gt;&amp;quot;FalseCJS&amp;quot;&lt;/code&gt; warning for the ESM artifacts in &lt;code&gt;moduleResolution: &amp;quot;node16&amp;quot;&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;I had some back-and-forth with Andrew Branch about this. The problem is that technically you &lt;em&gt;should&lt;/em&gt; have separate TS typedefs for &amp;quot;my artifacts in CJS mode&amp;quot;, and &amp;quot;my artifacts in ESM mode&amp;quot;, because &lt;a href=&#34;https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseCJS.md&#34;&gt;there can be actual differences in what&#39;s exported and how that gets accessed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The approach Andrew recommends to fix this is to actually compile your project with &lt;code&gt;tsc&lt;/code&gt; &lt;em&gt;twice&lt;/em&gt;, with two different TS module settings, and ship two different sets of typedefs with &lt;code&gt;.d.mts&lt;/code&gt; and &lt;code&gt;.d.ts&lt;/code&gt; extensions to match your &lt;code&gt;.mjs&lt;/code&gt; and &lt;code&gt;.cjs/js&lt;/code&gt; artifacts.&lt;/p&gt;

&lt;p&gt;Unfortunately, no build tool that I knew of at that time did this by default, and the idea of shipping 99%-duplicate typedefs bothered me. So, I opted to not try to fix this &lt;code&gt;&amp;quot;FalseCJS&amp;quot;&lt;/code&gt; issue for our packages (at least for the time being).&lt;/p&gt;

&lt;p&gt;Andrew Branch later filed &lt;a href=&#34;https://github.com/egoist/tsup/pull/934&#34;&gt;a PR for &lt;code&gt;tsup&lt;/code&gt; that tries to actually output one typedefs file per output format&lt;/a&gt;. As of writing this post, I have not yet actually tried this out myself, but I&#39;ll give it a shot later and see what happens.&lt;/p&gt;

&lt;p&gt;Note that Andrew currently has &lt;a href=&#34;https://gist.github.com/andrewbranch/79f872a8b9f0507c9c5f2641cfb3efa6&#34;&gt;a very long gist with his WIP comprehensive documentation on how TS interprets module formats&lt;/a&gt;, as well as &lt;a href=&#34;https://github.com/arethetypeswrong/arethetypeswrong.github.io/tree/main/docs/problems&#34;&gt;articles in the &lt;code&gt;are-the-types-wrong&lt;/code&gt; repo documenting all of the issues it can find&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&#34;round-2-results&#34;&gt;Round 2 Results&lt;/h3&gt;

&lt;p&gt;I published both &lt;a href=&#34;https://github.com/reduxjs/redux/releases/tag/v5.0.0-alpha.4&#34;&gt;&lt;code&gt;redux@5.0.0-alpha.4&lt;/code&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/releases/tag/v2.0.0-alpha.4&#34;&gt;&lt;code&gt;@reduxjs/toolkit@2.0.0-alpha.4&lt;/code&gt;&lt;/a&gt; in early April, with a set of package configurations that I was &lt;em&gt;fairly&lt;/em&gt; sure should actually be &amp;quot;correct&amp;quot;:&lt;/p&gt;

&lt;p&gt;I ended up with these configurations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redux:&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;main&amp;quot;: &amp;quot;dist/cjs/redux.cjs&amp;quot;,
  &amp;quot;module&amp;quot;: &amp;quot;dist/redux.mjs&amp;quot;,
  &amp;quot;types&amp;quot;: &amp;quot;dist/redux.d.ts&amp;quot;,
  &amp;quot;exports&amp;quot;: {
    &amp;quot;./package.json&amp;quot;: &amp;quot;./package.json&amp;quot;,
    &amp;quot;.&amp;quot;: {
      &amp;quot;types&amp;quot;: &amp;quot;./dist/redux.d.ts&amp;quot;,
      &amp;quot;import&amp;quot;: &amp;quot;./dist/redux.mjs&amp;quot;,
      &amp;quot;default&amp;quot;: &amp;quot;./dist/cjs/redux.cjs&amp;quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;ul&gt;
&lt;li&gt;Redux Toolkit:&lt;/li&gt;
&lt;/ul&gt;

&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{
  &amp;quot;module&amp;quot;: &amp;quot;dist/redux-toolkit.legacy-esm.js&amp;quot;,
  &amp;quot;main&amp;quot;: &amp;quot;dist/cjs/index.js&amp;quot;,
  &amp;quot;types&amp;quot;: &amp;quot;dist/index.d.ts&amp;quot;,
  &amp;quot;exports&amp;quot;: {
    &amp;quot;./package.json&amp;quot;: &amp;quot;./package.json&amp;quot;,
    &amp;quot;.&amp;quot;: {
      &amp;quot;types&amp;quot;: &amp;quot;./dist/index.d.ts&amp;quot;,
      &amp;quot;import&amp;quot;: &amp;quot;./dist/redux-toolkit.modern.mjs&amp;quot;,
      &amp;quot;default&amp;quot;: &amp;quot;./dist/cjs/index.js&amp;quot;
    },
    &amp;quot;./query&amp;quot;: {
      &amp;quot;types&amp;quot;: &amp;quot;./dist/query/index.d.ts&amp;quot;,
      &amp;quot;import&amp;quot;: &amp;quot;./dist/query/rtk-query.modern.mjs&amp;quot;,
      &amp;quot;default&amp;quot;: &amp;quot;./dist/query/cjs/index.js&amp;quot;
    },
    &amp;quot;./query/react&amp;quot;: {
      &amp;quot;types&amp;quot;: &amp;quot;./dist/query/react/index.d.ts&amp;quot;,
      &amp;quot;import&amp;quot;: &amp;quot;./dist/query/react/rtk-query-react.modern.mjs&amp;quot;,
      &amp;quot;default&amp;quot;: &amp;quot;./dist/query/react/cjs/index.js&amp;quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I also included the browser-focused ESM artifacts as well, although they aren&#39;t explicitly listed in there. (I may try to bring them back under the &lt;code&gt;&amp;quot;browser&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;unpkg&amp;quot;&lt;/code&gt; keys - will need to do more research there.)&lt;/p&gt;

&lt;p&gt;I also kept the nested entry point &lt;code&gt;package.json&lt;/code&gt; files in the RTK package as part of the Webpack 4 compat.&lt;/p&gt;

&lt;p&gt;These configurations seem to build and run in all of the sample projects I had configured, although that didn&#39;t include a React Native project.&lt;/p&gt;

&lt;h3 id=&#34;other-package-updates&#34;&gt;Other Package Updates&lt;/h3&gt;

&lt;p&gt;I later applied the same package updates to &lt;a href=&#34;https://github.com/reduxjs/reselect/releases/tag/v5.0.0-alpha.0&#34;&gt;&lt;code&gt;reselect@5.0.0-alpha.0&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I wasn&#39;t originally planning to do a major version release for React-Redux. However, after seeing some other potential breaking changes, I concluded it was worth &lt;a href=&#34;https://github.com/reduxjs/react-redux/issues/2026&#34;&gt;doing a React-Redux v9.0 major&lt;/a&gt; to include the packaging updates, handle TS types changes from Redux 5, and stop using the React 18 &lt;code&gt;useSyncExternalStore&lt;/code&gt; shim by default.&lt;/p&gt;

&lt;p&gt;As of this writing, I have &lt;a href=&#34;https://github.com/reduxjs/react-redux/pull/2038&#34;&gt;a PR open to update React-Redux&#39;s packaging&lt;/a&gt;, but had run into some TS issues and didn&#39;t get back to trying to fix those.&lt;/p&gt;

&lt;h2 id=&#34;updating-immer-s-packaging&#34;&gt;Updating Immer&#39;s Packaging&lt;/h2&gt;

&lt;p&gt;I did some perf checks on Immer 10 beta, and saw that it was significantly faster. However, I also noted that &lt;a href=&#34;https://github.com/immerjs/immer/pull/1028#issuecomment-1494549956&#34;&gt;somehow Immer 10 beta seemed &lt;em&gt;bigger&lt;/em&gt; than Immer 9&lt;/a&gt;. I pulled down &lt;a href=&#34;https://github.com/immerjs/immer/pull/1028&#34;&gt;the Immer 10 beta PR branch&lt;/a&gt; and ran some build size comparisons.&lt;/p&gt;

&lt;p&gt;After discussion, a part of the increase was due to Immer&#39;s &lt;code&gt;Map/Set&lt;/code&gt; support now being enabled by default, and Michel agreed to revert that since Redux doesn&#39;t need it and RTK is one of the biggest users of Immer. However, even with that change, &lt;a href=&#34;https://github.com/immerjs/immer/pull/1028#issuecomment-1499767135&#34;&gt;Immer 10 beta was still bigger than Immer 9&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I &lt;a href=&#34;https://github.com/immerjs/immer/pull/1028#issuecomment-1499805247&#34;&gt;dug into Immer&#39;s build system&lt;/a&gt;, and found out that it was still using the mostly-dead &lt;code&gt;tsdx&lt;/code&gt; build tooling package and targeting ES6 syntax. This was adding a bunch of polyfills and dead code. I also found some issues with the sourcemaps and the listed bundles.&lt;/p&gt;

&lt;p&gt;Since I&#39;d just spent a bunch of time updating the Redux and RTK build configs, I volunteered to port those changes over to Immer as well. I quickly put together a proof-of-concept, and saw noticeable reductions in Immer&#39;s bundle size. &lt;a href=&#34;https://github.com/immerjs/immer/pull/1032&#34;&gt;I put up a PR for those Immer changes&lt;/a&gt;, and Michel merged that as part of v10.&lt;/p&gt;

&lt;h2 id=&#34;problems-with-next-js-and-react-server-components&#34;&gt;Problems with Next.js and React Server Components&lt;/h2&gt;

&lt;p&gt;In early May, &lt;a href=&#34;https://nextjs.org/blog/next-13-4&#34;&gt;Next 13.4 was released&lt;/a&gt;. The headline feature was that the new &amp;quot;App Router&amp;quot;, which is based on React Server components, was now considered stable and ready for production. As part of that, Next&#39;s CLI defaulted to creating new projects with the App Router and &lt;code&gt;/app&lt;/code&gt; folder enabled out of the box, and the docs were updated to teach use of the App Router and React Server Components as the default.&lt;/p&gt;

&lt;p&gt;We soon began getting a stream of new issues filed against React-Redux and Redux Toolkit, complaining that React-Redux didn&#39;t work correctly. The main reports were errors being thrown because &lt;code&gt;React.createContext()&lt;/code&gt; was null or &lt;code&gt;useLayoutEffect&lt;/code&gt; not existing in an RSC environment.&lt;/p&gt;

&lt;p&gt;Meanwhile, my Redux co-maintainer &lt;a href=&#34;https://twitter.com/phry&#34;&gt;Lenz Weber-Tronic&lt;/a&gt;, who also works on Apollo Client for his day job, had spent the previous couple months doing research into how to use client-side state management and data fetching libraries with RSCs.&lt;/p&gt;

&lt;p&gt;One issue he&#39;d run into was how to use RTK Query&#39;s &lt;code&gt;createApi&lt;/code&gt;, which can generate React hooks, on both server and client, and he&#39;d &lt;a href=&#34;https://github.com/facebook/react/issues/26460&#34;&gt;filed a React issue asking for suggestions on how to handle this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;He also wrote &lt;a href=&#34;https://github.com/apollographql/apollo-client-nextjs/pull/9&#34;&gt;a long RFC for how to integrate Apollo and Next 13&lt;/a&gt;, which later led to &lt;a href=&#34;https://www.apollographql.com/blog/announcement/frontend/using-apollo-client-with-next-js-13-releasing-an-official-library-to-support-the-app-router/&#34;&gt;publishing an experimental Apollo + Next interop package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In mid-June, an Apollo user filed an issue reporting that &lt;a href=&#34;https://github.com/apollographql/apollo-client/issues/10974&#34;&gt;Apollo broke with Next 13.4.6-canary.2&lt;/a&gt;. That was fixed shortly thereafter in another canary build, but the issue spawned a long and frustrated discussion.&lt;/p&gt;

&lt;p&gt;In that thread, a Next dev reported that &lt;a href=&#34;https://github.com/apollographql/apollo-client/issues/10974#issuecomment-1593076110&#34;&gt;Next was now finding the ESM artifact&lt;/a&gt;, could thus better analyze what was being imported, and the use of client code in server components was now being considered an error. They mentioned: &amp;quot;If apollo client is going have server components solution then it needs to have a separate &lt;code&gt;&amp;quot;react-server&amp;quot;&lt;/code&gt; export condition that only contain the server only exports&amp;quot;.&lt;/p&gt;

&lt;p&gt;After reading that, I chimed in and noted that &lt;a href=&#34;https://github.com/apollographql/apollo-client/issues/10974#issuecomment-1593344051&#34;&gt;RTK Query has a mixture of both UI-agnostic and React-hooks-based code, and users might want to use &lt;code&gt;createApi&lt;/code&gt; on both server and client&lt;/a&gt;. I also pointed out that &lt;a href=&#34;https://github.com/apollographql/apollo-client/issues/10974#issuecomment-1593362951&#34;&gt;we pre-bundle RTK&#39;s artifacts&lt;/a&gt;, and I don&#39;t know how to further split those out just to satisfy these Next/RSC-imposed constraints.&lt;/p&gt;

&lt;p&gt;Seb Markbage, the React team&#39;s long-time lead architect (and now working on Next at Vercel), replied: &lt;a href=&#34;https://github.com/apollographql/apollo-client/issues/10974#issuecomment-1594629572&#34;&gt;&amp;quot;The user of your api can still use the same api, as long as you publish an optimized version of the inner implementation that excludes the unnecessary code branches.&amp;quot;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That led to a strongly worded debate. Lenz pointed out that &lt;a href=&#34;https://github.com/apollographql/apollo-client/issues/10974#issuecomment-1594645646&#34;&gt;this was asking the entire ecosystem to make potentially breaking packaging changes&lt;/a&gt;, especially since &lt;a href=&#34;https://github.com/apollographql/apollo-client/issues/10974#issuecomment-1594680297&#34;&gt;many packages like Apollo still don&#39;t have an &lt;code&gt;&amp;quot;exports&amp;quot;&lt;/code&gt; declaration&lt;/a&gt;. That seemed to be a surprise to Seb, who suggested &lt;a href=&#34;https://github.com/apollographql/apollo-client/issues/10974#issuecomment-1594746276&#34;&gt;an incredibly hacky workaround of &lt;code&gt;import * as React&lt;/code&gt;&lt;/a&gt; to fool their static analyzer.&lt;/p&gt;

&lt;p&gt;I got &lt;em&gt;extremely&lt;/em&gt; frustrated reading this exchange, and replied: &lt;a href=&#34;https://github.com/apollographql/apollo-client/issues/10974#issuecomment-1594894341&#34;&gt;&lt;strong&gt;&amp;quot;I&#39;ve spent &lt;em&gt;months&lt;/em&gt; trying to upgrade our packaging, and now you&#39;re telling me I have to do &lt;em&gt;more&lt;/em&gt; work just to keep our code from breaking in RSC environments. This is &lt;em&gt;very&lt;/em&gt; demoralizing.&amp;quot;&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The conversation in that particular thread died down, but also coincided with a whole bunch of debate threads about RSCs on Twitter and Reddit.&lt;/p&gt;

&lt;p&gt;A few weeks later, Lenz published an extensive post titled &lt;a href=&#34;https://phryneas.de/react-server-components-controversy&#34;&gt;&lt;strong&gt;My take on the current React &amp;amp; Server Components controversy&lt;/strong&gt;&lt;/a&gt;. In it, he noted that we think RSCs are a very useful technology, but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It&#39;s much harder for us to help our users, and they&#39;re filing a lot of new support issues&lt;/li&gt;
&lt;li&gt;There&#39;s a lot more about React (and Next) we now have to understand&lt;/li&gt;
&lt;li&gt;It&#39;s now &lt;em&gt;much&lt;/em&gt; harder to maintain and publish a library that works with React&lt;/li&gt;
&lt;li&gt;It feels like there&#39;s been very poor communication from the React team about the status of RSCs and the &lt;code&gt;use&lt;/code&gt; hook, and little discussion on how this will impact the ecosystem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;He also listed a number of possible APIs that would help libraries better deal with RSC environments and data fetching.&lt;/p&gt;

&lt;p&gt;Lenz&#39;s post received &lt;a href=&#34;https://twitter.com/phry/status/1676691019994112004&#34;&gt;lots of strong positive feedback&lt;/a&gt; from folks agreeing with the list of issues and suggestions, and expressing sympathy.&lt;/p&gt;

&lt;p&gt;We never really got any actual response from the React team around any of those API suggestions, or how to properly publish packages that cooperate with RSCs. I &lt;em&gt;did&lt;/em&gt; get some outreach from some folks in the React org who are trying to work on adding official docs around RSCs, and was able to pass on a lot of community feedback around RSCs, marketing, and usage concerns.&lt;/p&gt;

&lt;p&gt;The Next docs did get a page covering &lt;a href=&#34;https://nextjs.org/docs/getting-started/react-essentials#rendering-third-party-context-providers-in-server-components&#34;&gt;how to wrap third-party context providers with &lt;code&gt;&amp;quot;use client&amp;quot;&lt;/code&gt;&lt;/a&gt;, although that feels like a bit of a band-aid.&lt;/p&gt;

&lt;h2 id=&#34;venting&#34;&gt;Venting&lt;/h2&gt;

&lt;p&gt;After spending so much time on these changes, I was getting fairly frustrated at the sheer number of things I was having to keep track of.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://twitter.com/acemarke/status/1652021889307496448&#34;&gt;In late April, I tweeted&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Things I have to keep in mind when publishing a library in 2023:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build artifact formats (ESM, CJS, UMD)

&lt;ul&gt;
&lt;li&gt;Matrixed with: dev/prod/NODE_ENV builds&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Bundled or individual .js per source&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exports&lt;/code&gt; setup&lt;/li&gt;
&lt;li&gt;Webpack 4 limits&lt;/li&gt;
&lt;li&gt;TS &lt;code&gt;moduleResolution&lt;/code&gt; options&lt;/li&gt;
&lt;li&gt;User environments&lt;/li&gt;
&lt;li&gt;Behavior differences between bundlers&lt;/li&gt;
&lt;li&gt;Node ESM/CJS modes&lt;/li&gt;
&lt;li&gt;TS typedef output (bundled? individual? &lt;code&gt;.d.ts&lt;/code&gt;, or &lt;code&gt;.d.mts&lt;/code&gt;?)&lt;/li&gt;
&lt;li&gt;Edge runtimes?&lt;/li&gt;
&lt;li&gt;And now React&#39;s new &lt;code&gt;&amp;quot;use client&amp;quot;&lt;/code&gt; and RSC constraints&lt;/li&gt;
&lt;li&gt;All of this for upstream deps too&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is getting utterly ridiculous :(&lt;/p&gt;

&lt;p&gt;I don&#39;t know how anyone is supposed to be able to keep up with all these possible configuration changes, edge cases, runtime environments, and conflicting constraints.&lt;/p&gt;

&lt;p&gt;And there are no actual comprehensive guides on how to do this stuff. Everyone&#39;s cargo-culting from others.&lt;/p&gt;

&lt;p&gt;I&#39;m trying to do right by our users and publish packages that work in as many environments as reasonably possible, but this is incredibly frustrating to deal with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It&#39;s a miracle anything about this ecosystem works at all.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This struck a nerve. The tweet went pretty viral (for me), with dozens of retweets, quotes, and replies. It also got linked in &lt;a href=&#34;https://javascriptweekly.com/issues/637&#34;&gt;some newsletters&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;Similarly, after I wrote my comment about &amp;quot;feeling demoralized&amp;quot; in response to RSC changes, I followed that up with &lt;a href=&#34;https://twitter.com/acemarke/status/1669733564378673152&#34;&gt;another tweet linking the discussion and venting&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As a library maintainer in the React ecosystem, I&#39;m getting pretty frustrated by the churn around React Server Components.&lt;/p&gt;

&lt;p&gt;Really starting to question whether the touted benefits are worth the pain being inflicted on lib maintainers&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That tweet also spread pretty widely and got a lot of reactions as well.&lt;/p&gt;

&lt;p&gt;A few days later, &lt;a href=&#34;https://twitter.com/acemarke/status/1669808482915057664&#34;&gt;I had a follow-up thought&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I find it ironic that both of my recent tweets a/b frustrations dealing with JS ecosystem churn as a lib maintainer (package setup, RSCs) have gone viral.&lt;/p&gt;

&lt;p&gt;I normally try to stay positive and not gripe much publicly.&lt;/p&gt;

&lt;p&gt;I guess other folks feel or sympathize with those frustrations&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As one reply noted: &amp;quot;I think people know how patient and positive you are towards what you&#39;re doing and the ecosystem. If something makes you frustrated that means that something BIG isn&#39;t working right or it&#39;s wrong&amp;quot;.&lt;/p&gt;

&lt;h2 id=&#34;final-thoughts&#34;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;I usually like to write blog posts like this after some release is done, or some discussion has come to an end, when it feels like that story is complete and there&#39;s some concrete takeaways and answers to write about. It&#39;d be great if I could say &amp;quot;hey, RTK 2.0 is published, and it includes a set of packaging updates that I know are correct and work everywhere&amp;quot;.&lt;/p&gt;

&lt;p&gt;Sadly, that&#39;s not the case here.&lt;/p&gt;

&lt;p&gt;This has been an extremely busy summer for me across work, Redux, and personal time, and I&#39;ve realized I&#39;m dealing with some burnout. But, also, I started this post at the beginning of June coming back from React Summit, and have just now gotten back to it a couple months later to get it wrapped up.&lt;/p&gt;

&lt;h3 id=&#34;where-do-things-stand-today&#34;&gt;Where Do Things Stand Today?&lt;/h3&gt;

&lt;p&gt;Here&#39;s the state of things as of today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/releases/tag/v2.0.0-beta.0&#34;&gt;Redux Toolkit 2.0.0-beta.0&lt;/a&gt; and &lt;a href=&#34;https://github.com/reduxjs/redux/releases/tag/v5.0.0-beta.0&#34;&gt;Redux 5.0.0-beta.0&lt;/a&gt; are live and available, with updated ESM/CJS packaging (and a lot of other feature changes and TS types updates)

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/reduxjs/reselect/releases/tag/v5.0.0-alpha.2&#34;&gt;Reselect 5.0.0-alpha.2&lt;/a&gt; and &lt;a href=&#34;https://github.com/reduxjs/redux-thunk/releases/tag/v3.0.0-alpha.3&#34;&gt;Redux-Thunk 3.0.0-alpha.3&lt;/a&gt; are out as well, with both packaging updates and other tweaks&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;I have &lt;a href=&#34;https://github.com/reduxjs/react-redux/pull/2038&#34;&gt;a WIP PR to update React-Redux&#39;s packaging for v9&lt;/a&gt;, but there&#39;s no alpha release yet with those changes

&lt;ul&gt;
&lt;li&gt;Lenz worked on several changes to React-Redux&#39;s use of Context to keep things from breaking with RSCs. The first changes went out in &lt;a href=&#34;https://github.com/reduxjs/react-redux/releases/tag/v8.1.0&#34;&gt;v8.1.0&lt;/a&gt;, followed by later tweaks in &lt;a href=&#34;https://github.com/reduxjs/react-redux/releases/tag/v8.1.1&#34;&gt;v8.1.1&lt;/a&gt; and &lt;a href=&#34;https://github.com/reduxjs/react-redux/releases/tag/v8.1.2&#34;&gt;v8.1.2&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The packages &lt;em&gt;mostly&lt;/em&gt; pass the &lt;code&gt;are-the-types-wrong&lt;/code&gt; checks, but still exhibit the &lt;code&gt;&amp;quot;FalseCJS&amp;quot;&lt;/code&gt; warning. Also, &lt;a href=&#34;https://arethetypeswrong.github.io/?p=%40reduxjs%2Ftoolkit%402.0.0-beta.0&#34;&gt;RTK 2.0 beta has some internal TS path usages that need to be cleaned up&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Beyond the Context-related tweaks, we don&#39;t have any actual changes for better interop with RSCs, or plans to work on anyhting meaningful there&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;lessons-and-takeaways&#34;&gt;Lessons and Takeaways&lt;/h3&gt;

&lt;p&gt;I&#39;ve said many times that I still feel like I barely know anything about the topics of module packaging and publishing types. In practice, I&#39;d guess that I do actually know more than most JS devs, because I&#39;ve had to spend so much time trying to work on this (both over the years, and this year specifically). But, given the insane complexity, myriad of conflicting requirements, and rapidly changing list of things to keep track of, I think it&#39;s pretty understandable that I still feel like a clueless imposter about all of these topics.&lt;/p&gt;

&lt;p&gt;So, what have I &lt;em&gt;actually&lt;/em&gt; learned?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I have a set of package configurations that &lt;em&gt;seem&lt;/em&gt; to work in most bundlers and build tools right now, and &lt;em&gt;seem&lt;/em&gt; to have valid ESM/CJS packaging&lt;/li&gt;
&lt;li&gt;Publishing TS typedefs properly adds another level of complexity on top of that&lt;/li&gt;
&lt;li&gt;Pre-bundling your JS build artifacts sidesteps potential issues around having to have &lt;code&gt;&amp;quot;.js&amp;quot;&lt;/code&gt; in file imports, and seems to work okay with tree-shaking...&lt;/li&gt;
&lt;li&gt;But then can lead to other problems when something like this &amp;quot;split out your client code for RSC scenarios&amp;quot; thing comes up&lt;/li&gt;
&lt;li&gt;It&#39;s almost impossible to keep up with all the different tools and constraints that are out there, and they keep changing

&lt;ul&gt;
&lt;li&gt;There is no good full list of build tools and their quirks or constraints. There&#39;s &lt;em&gt;some&lt;/em&gt; resources ( &lt;a href=&#34;https://sokra.github.io/interop-test/&#34;&gt;Sokra&#39;s interop table&lt;/a&gt;, &lt;a href=&#34;https://reaper.is/writing/20220418-the-esm-cjs-problem&#34;&gt;this article with some bundler details&lt;/a&gt;, &lt;a href=&#34;https://docs.google.com/spreadsheets/d/1VzemJcrAerkMyw17VZo3uAODbC4dmRUgbc2_jXuveCQ/edit#gid=0&#34;&gt;a spreadsheet from Jason Miller&lt;/a&gt;, etc), but there&#39;s no one-stop-shop to understand what you need to configure to make specific tools happy.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Similarly, there just aren&#39;t enough official, comprehensive resources on publishing packages. I found &lt;em&gt;some&lt;/em&gt; decent guides ( such as &lt;a href=&#34;https://github.com/frehner/modern-guide-to-packaging-js-library&#34;&gt;The Modern Guide to Packaging Your JS Library&lt;/a&gt; , &lt;a href=&#34;https://github.com/advename/The-React-Library-guide&#34;&gt;The React Library Guide (draft)&lt;/a&gt; , and &lt;a href=&#34;https://web.dev/publish-modern-javascript/&#34;&gt;Publishing Modern JS&lt;/a&gt; ), but it still feels like so much of this knowledge is fragmented, scattered, and conflicting. There&#39;s especially a need for guidance on what package formats+artifacts you &lt;em&gt;ought&lt;/em&gt; to be shipping to cover different kinds of usage scenarios.&lt;/li&gt;
&lt;li&gt;The ecosystem desperately needs better tooling to help automate this process.

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tsup&lt;/code&gt; seems to be pretty good, and I&#39;ve seen some other tools that claim to help with shipping dual ESM/CJS packages that I haven&#39;t tried, but it just feels like so much of this could be automated.&lt;/li&gt;
&lt;li&gt;Similarly, it feels like there&#39;s a need for some kind of &amp;quot;test-your-lib-against-a-range-of-build-tools As A Service&amp;quot; tool. I set up a bunch of sample Redux projects with a variety of build tools, and I saw &lt;code&gt;react-aria&lt;/code&gt; did something similar, but this feels like the kind of setup that could be commoditized somehow and help lib authors verify that their packages work correctly across the ecosystem.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;React Server Components are a useful concept and tool, but it sure feels like this is a major disruption that&#39;s going to break a lot of the ecosystem. I understand the React team&#39;s comments that &amp;quot;nothing about client React changes, this is all additive&amp;quot;... but at the same time it&#39;s a massive increase in mental overhead and use case complexity that both users and lib authors have to deal with.

&lt;ul&gt;
&lt;li&gt;There&#39;s been effectively no outreach from the React team to the library ecosystem about how to deal with packages and RSCs. To be fair, we did have a call with Dan+Andrew, Dan reviewed Lenz&#39;s RFC, and there&#39;s been some discussion in issues. But there was no announcement or warning about Next throwing errors on client imports, no table of &amp;quot;what&#39;s in each canary version?&amp;quot; available, and no kind of &amp;quot;guidance to lib authors for RSC compat&amp;quot; post or doc published.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;The overall ecosystem CJS/ESM transition has been a long and ongoing nightmare, and it shows no signs of ending any time soon. Just recently I saw a pair of dueling posts that argued &lt;a href=&#34;https://deno.com/blog/commonjs-is-hurting-javascript&#34;&gt;&amp;quot;CJS is hurting JavaScript&amp;quot;&lt;/a&gt;, and &lt;a href=&#34;https://bun.sh/blog/commonjs-is-not-going-away&#34;&gt;&amp;quot;CommonJS is not going away&amp;quot;&lt;/a&gt;. Clearly this is a problem we&#39;re going to be stuck with for years.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;future-steps&#34;&gt;Future Steps&lt;/h3&gt;

&lt;p&gt;We still need to finish up Redux Toolkit 2.0, but that&#39;s going to take a while. Just trying to make sure all the packages are fully up to date with the packaging changes, cross-reference each other&#39;s versions, and that all the TS types work, is time-consuming. We probably have more code-related changes to make too, but we don&#39;t have a solid list of what else &lt;em&gt;must&lt;/em&gt; be in this set of majors.&lt;/p&gt;

&lt;p&gt;Additionally, all of us maintainers are dealing with trying to balance jobs, motivation, time, and real life, and that means Redux work is a lower priority for us right now.&lt;/p&gt;

&lt;p&gt;It&#39;s been an exhausting year so far dealing with all these issues. We still intend to get out the set of major releases (eventually - absolutely no ETA promises here), and I&#39;m &lt;em&gt;hopeful&lt;/em&gt; that these new versions will be a benefit to the ecosystem and significantly improve compatibility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I sure &lt;em&gt;hope&lt;/em&gt; that all this time and effort will have been worth it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;further-information&#34;&gt;Further Information&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ES Modules History and Specs&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/jkrems/769a8cd8806f7f57903b641c74b5f08a&#34;&gt;Gist: ES Modules - History and Future&lt;/a&gt; (links to spec drafts and TC39 notes)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://nodejs.org/docs/latest-v20.x/api/packages.html&#34;&gt;Node API reference: Packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://nodejs.org/api/packages.html#dual-package-hazard&#34;&gt;Packages: the &amp;quot;Dual-Package Hazard&amp;quot; problem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://nodejs.org/docs/latest-v20.x/api/esm.html&#34;&gt;Node API Reference: ECMAScript Modules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Andrew Branch&#39;s &lt;a href=&#34;https://gist.github.com/andrewbranch/79f872a8b9f0507c9c5f2641cfb3efa6&#34;&gt;WIP TypeScript module processing documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ESM/CJS Debates&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c&#34;&gt;Sindre Sorhus: Pure ESM packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/joepie91/bca2fda868c1e8b2c2caf76af7dfcad3&#34;&gt;ES Modules are terrible, actually&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://deno.com/blog/commonjs-is-hurting-javascript&#34;&gt;CommonJS is Hurting JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bun.sh/blog/commonjs-is-not-going-away&#34;&gt;CommonJS is Not Going Away&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Package Publishing Resources&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/markerikson/42d55b0fd970449fc5d84263f4775cbd&#34;&gt;Redux Toolkit ESM/TS migration discussions (Mateusz Burzynski and Andrew Branch)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/frehner/modern-guide-to-packaging-js-library&#34;&gt;The Modern Guide to Packaging Your JS Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/advename/The-React-Library-guide&#34;&gt;The React Library Guide (draft)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://webreflection.medium.com/a-nodejs-dual-module-deep-dive-8f94ff56210e&#34;&gt;A NodeJS Dual Module Deep Dive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://antfu.me/posts/publish-esm-and-cjs&#34;&gt;Ship ESM &amp;amp; CJS In One Package&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://2ality.com/2022/01/esm-specifiers.html&#34;&gt;Publishing and Consuming ES Modules via Packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://dev.to/jakobjingleheimer/configuring-commonjs-es-modules-for-nodejs-12ed#esm-source-and-both-cjs-amp-esm-distribution&#34;&gt;Configuring CommonJS &amp;amp; ES Modules for Node.js &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.sensedeep.com/blog/posts/2021/how-to-create-single-source-npm-module.html&#34;&gt;How to Create a Hybrid NPM Module for ESM and CommonJS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://reaper.is/writing/20220418-the-esm-cjs-problem&#34;&gt;The ESM and CJS Problem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://evertpot.com/universal-commonjs-esm-typescript-packages/&#34;&gt;Supporting CommonJS and ESM with TypeScript and Node&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tools&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://tsup.egoist.dev/&#34;&gt;&lt;code&gt;tsup&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://arethetypeswrong.github.io/&#34;&gt;Are The Types Wrong?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://publint.dev/&#34;&gt;Publint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://preconstruct.tools/&#34;&gt;Preconstruct&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/release-it/release-it&#34;&gt;&lt;code&gt;release-it&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.npmjs.com/package/yalc&#34;&gt;&lt;code&gt;yalc&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/tree/32e90810b8e4a7b9f274d47bc8cdad8776398947/examples/publish-ci&#34;&gt;RTK CI example projects for various build tools&lt;/a&gt; and &lt;a href=&#34;https://github.com/reduxjs/redux-toolkit/blob/32e90810b8e4a7b9f274d47bc8cdad8776398947/.github/workflows/tests.yml#L143-L205&#34;&gt;CI workflow to test the package build artifact&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    
    <item>
      <title>Presentations: Debugging JavaScript</title>
      <link>https://blog.isquaredsoftware.com/2023/06/presentations-debugging-javascript/</link>
      <pubDate>Thu, 01 Jun 2023 10:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2023/06/presentations-debugging-javascript/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;In mid-2021 I had the chance to do a talk on &amp;quot;Debugging Software&amp;quot; for a meetup hosted by Mintbean.io. In 2022, I did an updated &amp;quot;Debugging JS&amp;quot; version of the talk for ThisDot Media&#39;s &amp;quot;JS Drops&amp;quot; video series.&lt;/p&gt;

&lt;p&gt;I previously did a post on &lt;a href=&#34;https://blog.isquaredsoftware.com/2019/01/blogged-answers-debugging-tips/&#34;&gt;&lt;strong&gt;Debugging Tips&lt;/strong&gt;&lt;/a&gt;, where I listed some quick tips for thinking about debugging, and recapped the stories of several interesting bugs I ran into and solved.&lt;/p&gt;

&lt;p&gt;I later had a chance to present this talk at React Summit 2023 in Amsterdam.&lt;/p&gt;

&lt;p&gt;This talk was based on that post, and covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concepts and principles for thinking about debugging, as well as some additional tips&lt;/li&gt;
&lt;li&gt;Specific techniques for debugging, including how to use both print logging and GUI debuggers effectively, as well strategies for debugging React, Redux, and JS&lt;/li&gt;
&lt;li&gt;A quick example of using &lt;a href=&#34;https://replay.io&#34;&gt;Replay&lt;/a&gt; to investigate bugs using time-travel debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The slides also include some &amp;quot;Scene of the crime&amp;quot;-themed versions of some of those debugging stories (not covered in the video due to time constraints).&lt;/p&gt;

&lt;h3 id=&#34;debugging-js-slides-presentations-2023-06-debugging-js&#34;&gt;&lt;a href=&#34;https://blog.isquaredsoftware.com/presentations/2023-06-debugging-js/&#34;&gt;Debugging JS - slides&lt;/a&gt;&lt;/h3&gt;

&lt;h3 id=&#34;debugging-js-video-react-summit-2023-https-www-youtube-com-live-ima0r8cmkge-feature-share-t-19387&#34;&gt;&lt;a href=&#34;https://www.youtube.com/live/ima0r8CmkGE?feature=share&amp;amp;t=19387&#34;&gt;Debugging JS - video (React Summit 2023)&lt;/a&gt;&lt;/h3&gt;

&lt;h3 id=&#34;debugging-js-video-js-drops-https-www-youtube-com-watch-v-uvyp63su12s&#34;&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=uVYP63Su12s&#34;&gt;Debugging JS - video (&amp;quot;JS Drops&amp;quot;)&lt;/a&gt;&lt;/h3&gt;</description>
    </item>
    
    <item>
      <title>Presentations: 2022 Podcasts</title>
      <link>https://blog.isquaredsoftware.com/2022/12/presentations-2022-podcasts/</link>
      <pubDate>Sun, 11 Dec 2022 12:00:00 -0500</pubDate>
      
      <guid>https://blog.isquaredsoftware.com/2022/12/presentations-2022-podcasts/</guid>
      <description>&lt;p&gt;&lt;/p&gt;

&lt;p&gt;I had the opportunity to talk on a number of different podcasts and interviews over the course of the year. I&#39;ve gathered them here as a directory.&lt;/p&gt;

&lt;h2 id=&#34;thisdot-tracy-lee-how-to-contribute-to-redux&#34;&gt;ThisDot / Tracy Lee: How to Contribute to Redux&lt;/h2&gt;

&lt;p&gt;Tracy Lee is a prolific podcaster, and her company ThisDot creates numerous shows related to the JS ecosystem. She had me on as part of a new &amp;quot;How to Contribute...&amp;quot; series, where I talked about ways to contribute to the Redux libraries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=rPJmnxDX9lY&#34;&gt;https://www.youtube.com/watch?v=rPJmnxDX9lY&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;kevin-ghadyani-redux-vs-react-context&#34;&gt;Kevin Ghadyani: Redux vs React Context&lt;/h2&gt;

&lt;p&gt;Kevin and I have done a couple long-form video discussions in the last couple years, and he&#39;s split those out into several separate videos.&lt;/p&gt;

&lt;p&gt;This discussion was actually recorded in mid-2021, but just recently got published. We talked about the actual differences between Context and Redux, and why so many people get confused about the differences.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=1bIdaWVMFkc&#34;&gt;https://www.youtube.com/watch?v=1bIdaWVMFkc&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;podrocket-time-travel-debugging-with-replay-with-jason-laster&#34;&gt;PodRocket: Time-Travel Debugging with Replay (with Jason Laster)&lt;/h2&gt;

&lt;p&gt;I previously was a guest on the PodRocket podcast to discuss Redux topics. Shortly after I started working at Replay, they had me on again along with our CEO Jason Laster. We talked about the differences between Replay and &amp;quot;session recording&amp;quot; tools, the internals of how Replay works, and potential future use cases for time-travel debugging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://podrocket.logrocket.com/replay&#34;&gt;https://podrocket.logrocket.com/replay&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;guild-community-tour-mark-erikson&#34;&gt;Guild Community Tour: Mark Erikson&lt;/h2&gt;

&lt;p&gt;Taz Singh does a lot of interviews with folks in the JS community to help share their stories. He interviewed several folks at the Reactathon conference this year, and we had a chance to sit down and chat. We made a bunch of jokes about my Simpsons avatar, and talked about my early dev career, my time teaching in China, how I got involved in Redux, what prompted some of my blog posts, and the magic of time travel debugging with Replay.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://beta.guild.host/presentations/episode-23-mark-erikson-bczaup&#34;&gt;https://beta.guild.host/presentations/episode-23-mark-erikson-bczaup&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;peerlist-the-mindset-of-a-redux-maintainer&#34;&gt;Peerlist: The Mindset of a Redux Maintainer&lt;/h2&gt;

&lt;p&gt;This was a meetup-type presentation of the &amp;quot;Modern Redux&amp;quot; talk I&#39;ve done a couple times, but there were also some good questions asked afterwards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=MbREkTZCcpc&#34;&gt;https://www.youtube.com/watch?v=MbREkTZCcpc&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;20-minute-js-redux-toolkit-and-state-management-in-react&#34;&gt;20 Minute JS: Redux Toolkit and State Management in React&lt;/h2&gt;

&lt;p&gt;Fernando Doglio had me on to discuss some of the basics around &amp;quot;state management&amp;quot;, why Redux became popular and then got a bad reputation, comparisons with other state libraries, and how we&#39;ve modernized it with Redux Toolkit&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://podcast.20minjs.com/1952066/10665172-episode-12-redux-toolkit-and-state-management-in-react-with-mark-erikson&#34;&gt;https://podcast.20minjs.com/1952066/10665172-episode-12-redux-toolkit-and-state-management-in-react-with-mark-erikson&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;react-native-radio-a-redux-maintainer-s-thoughts-on-redux-toolkit-vs-mobx-state-tree&#34;&gt;React Native Radio: A Redux Maintainer&#39;s Thoughts on Redux Toolkit vs Mobx-State-Tree&lt;/h2&gt;

&lt;p&gt;Earlier this year the React Native Radio podcast hosts did a show on &lt;a href=&#34;https://reactnativeradio.com/episodes/rnr-241-redux-toolkit-vs-mobx-state-tree-showdown&#34;&gt;Redux Toolkit vs Mobx-State-Tree&lt;/a&gt;. It was actually a very fair and balanced discussion, with a bit of a twist because host Jamon Holmgren is the maintainer of MST.&lt;/p&gt;

&lt;p&gt;After listening to that episode, I had some thoughts on some of the topics they discussed, and reached out to Jamon. They brought me on for a follow-up episode where we dove into some of the points they&#39;d brought up and I talked about &lt;em&gt;why&lt;/em&gt; Redux is designed this way, including the purpose of immutability, pain points with selectors, and other tradeoffs. Really good discussion!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://reactnativeradio.com/episodes/rnr-249-a-redux-maintainers-thoughts-on-rtk-vs-mst&#34;&gt;https://reactnativeradio.com/episodes/rnr-249-a-redux-maintainers-thoughts-on-rtk-vs-mst&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;merged-leading-tech-communities&#34;&gt;Merged: Leading Tech Communities&lt;/h2&gt;

&lt;p&gt;Iddan Aaronsohn had me on the &amp;quot;Merged&amp;quot; podcast to discuss a number of topics around my involvement in the tech community. We talked about dealing with social media, sharing knowledge, working with open source, and more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://open.spotify.com/episode/67jTvkMB2vf7AYD5d8KSEs?si=DmNMOIuOSjaheIRI09-G_A&amp;amp;nd=1&#34;&gt;https://open.spotify.com/episode/67jTvkMB2vf7AYD5d8KSEs?si=DmNMOIuOSjaheIRI09-G_A&amp;amp;nd=1&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&#34;reactiflux-office-hours-lenz-weber-tronic-and-mark-erikson&#34;&gt;Reactiflux Office Hours: Lenz Weber-Tronic and Mark Erikson&lt;/h2&gt;

&lt;p&gt;Carl Vitullo, one of the other admins in the Reactiflux Discord, held an &amp;quot;office hours&amp;quot; interview with myself and my RTK co-maintainer Lenz Weber-Tronic. We chatted about how we got involved with Redux, how users depend on implicit behavior of libraries, complexities of maintaining TypeScript libraries, the job searches we went through this year, and ways that people can get involved with open source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&#34;https://open.spotify.com/episode/1xKYFWjPmtYwNY3DauQ2JB?si=LOhGBIrDQ5KI3034b6xvBQ&#34;&gt;https://open.spotify.com/episode/1xKYFWjPmtYwNY3DauQ2JB?si=LOhGBIrDQ5KI3034b6xvBQ&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    
  </channel>
</rss>