<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Zach Shallbetter — Writing</title>
    <link>https://zachshallbetter.com/writing</link>
    <atom:link href="https://zachshallbetter.com/rss.xml" rel="self" type="application/rss+xml" />
    <description>Essays by Zach Shallbetter on product, systems, AI, leadership, and creative technology.</description>
    <language>en</language>
    <managingEditor>hi@zachshallbetter.com (Zach Shallbetter)</managingEditor>
    <webMaster>hi@zachshallbetter.com (Zach Shallbetter)</webMaster>
    <item>
      <title>I Built an App So My Lady Could Pass the CAPM</title>
      <link>https://zachshallbetter.com/writing/i-built-an-app-so-my-lady-could-pass-the-capm</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/i-built-an-app-so-my-lady-could-pass-the-capm</guid>
      <pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>A native iOS app for my lady's CAPM prep, and the one rule it's built on: derive, don't ask.</description>
      <content:encoded><![CDATA[<h2>Derive, don&#39;t ask: what a one-user product teaches about onboarding, and about teaching itself</h2>
<p>My lady Miranda is studying for the CAPM, the entry certification for project management. The prep options were the usual suspects: PDF dumps, question banks with interfaces from 2011, subscription sites that gate everything useful behind a paywall before showing you a single question. She needed a study plan, spaced repetition, and something that did not feel like punishment after a full workday.</p>
<p>I build software. So I built her the app.</p>
<p>Ascent went live on the App Store yesterday. It is a native SwiftUI app with 1,122 questions across the four CAPM domains, every one carrying a written explanation of why each answer is right and the others wrong, organized into 36 lessons, a placement quiz that never feels like a test, and a Boss exam scored against the real pass mark. It runs on Fundamental, the physics engine I built, which the entire interface is composited inside. This essay is not really a launch announcement, though. It is about a single design rule the app is built on, top to bottom, which I think most software gets backwards: <strong>derive, don&#39;t ask.</strong></p>
<h2>The rule: derive, don&#39;t ask</h2>
<p>Open most apps in this category and the first thing you meet is a form. Name, email, goals, experience level, preferred study times, a marketing-consent checkbox. The product asks you to do data entry before it has demonstrated a single unit of value. Every question before value is a dropout risk, and the industry knows it, and the forms persist anyway, because asking is easier than deriving.</p>
<p>Ascent opens into the product. First screen: <em>Pass the CAPM. Answer three questions, we&#39;ll build your study plan.</em> No account, no email, no name. You are learning before you notice you were being onboarded.</p>
<p>Everything the app needs, it derives. Your goal comes from your exam date, because the date implies the pace. Your readiness comes from how you answer placement questions, not from a self-assessment dropdown, because people are bad at self-assessment and quiz behavior does not lie. Identity starts as an anonymous account created silently on first launch, so progress syncs from minute one; if you later want it on a second device, Sign in with Apple links the account you already have. The app never asks for what it can calculate.</p>
<p>There is a corollary that matters just as much: <strong>no silent wrong defaults.</strong> Deriving means the app makes assumptions, and an assumption the user cannot see is a bug waiting to embarrass you. If the default exam countdown says sixty days and her exam is next week, the daily plan is wrong in a way that compounds. So setting the exam date is not a buried default you have to catch. It is the last step of onboarding, pre-filled with a guess and put directly in front of you to confirm or change, before you ever reach the app.</p>
<p>The same restraint governs permissions. Ascent does not ask to send notifications on first launch, when it has done nothing for you and the ask is pure imposition. It asks after you finish your first lesson, once it has actually earned a place on your lock screen. Permission is a thing you grant to software that has already been useful, not a toll you pay to try it.</p>
<p>Ask only what you cannot derive. Surface everything you assumed. Earn everything you request. That is the whole onboarding.</p>
<h2>Why a user of one makes the design honest</h2>
<p>Building for one specific person is the best design constraint I know. Miranda is not a persona or an aggregate. She studies after work, tired, on a phone. Every friction I might have shrugged off as acceptable, I watched cost her real minutes and real patience. A signup form would not have been a conversion-funnel abstraction; it would have been my partner, on the couch, giving up for the night.</p>
<p>The same honesty runs straight through to how the app teaches, because the derive-don&#39;t-ask rule is not only about onboarding. Asking a tired person to configure their study preferences is offloading the product&#39;s job onto the user. The exam date, the placement results, the entire answer history: the app has everything it needs to do its own job. So it does.</p>
<h2>How it teaches: a memory model, not a syllabus</h2>
<p>It starts by finding out where Miranda actually is. Onboarding asks how ready she <em>feels</em>, a single confidence slider, and then, with the particle field deliberately switched off so nothing competes for her attention, gives her three real questions. The reveal puts the two numbers side by side: how ready you feel, how ready you are. The felt number is a foil; the study plan runs on the measured one. It is the whole rule at the moment of first contact. The app would rather show you the gap than take your word for it. (That the field goes dark for the quiz is the same discipline as everywhere else: the ambience gets out of the way in exactly the moment focus matters.)</p>
<p>Under the lessons is a spaced-repetition engine. Every question is a flashcard with a small memory model attached: an interval, an ease factor, a repetition count, a lapse count, a due date. Answer it correctly and the interval stretches, one day, then three, then multiplied out by the card&#39;s ease each time, and the card drifts toward the back of the deck. Miss it and the interval collapses to a single day, the lapse count ticks up, the ease drops, and the card jumps the queue. This is the SM-2 algorithm that every serious flashcard app is built on, tuned so that a question seen three clean times counts as mastered and stops taking your time.</p>
<p>The daily route is not a fixed syllabus. It is computed, every session, from that memory model. A priority score ranks all 1,122 questions at once: a question you have never seen scores high, a question that is overdue scores higher, one you have lapsed on repeatedly higher still. A question you have answered right three times, comfortably, on schedule, scores <em>negative</em> and drops away. The plan is the top of that ranking, capped so no single topic dominates, then shuffled so it never feels mechanical. What you drill tomorrow is a function of what you got wrong today.</p>
<p>Readiness works the same way: derived, never self-reported. The ring that fills as you study is a four-factor score computed per domain. Your accuracy, how much of the domain you have actually covered, how much you have <em>retained</em> rather than just seen once, and how broadly your strength spreads across the sub-topics. Those four are weighted by the real exam&#39;s domain blueprint and blended into one number, with a deliberate handoff: early on, before there is enough live data, the ring leans on your placement quiz; as coverage grows past halfway, it leans entirely on your behavior. The number is meaningful on day one and honest by the end.</p>
<p>And it finds your weak spots three different ways, because &quot;weak&quot; has more than one shape. It knows your weakest <em>domain</em>. It sorts every question into one of about sixty topic areas, earned value, critical path, risk response, the agile ceremonies, OPAs and EEFs, and knows the weakest of those. And it tracks an &quot;Achilles&#39; heel&quot;: the question <em>formats</em> you keep missing (scenario questions, sequencing) and the specific repeat-offender questions you have gotten wrong two or more times. A comfortable plan that reviews what you already know feels productive and quietly fails you on exam day. This one refuses to; it is built to be honest about what she does not know, because that is the only thing worth her evening.</p>
<p>None of this feels like a spreadsheet, because the questions do not all wear the same clothes. There are six formats: true/false, multiple choice, matching, hotspot, scenario, and sequencing. The curriculum is a <em>path</em> you climb rather than a list you scroll, with the whole four-domain outline laid out as a route and your current position glowing on it. Woven through it are eight short branching conversations, a sponsor named Priya asking what you need from her before the project spends a dollar, where the &quot;question&quot; is a decision and the wrong choice teaches by consequence. There is a timed Boss exam scored against the real pass mark, a flashcard deck for the pure-recall material, and a one-tap formula sheet for exam-day math. Same memory model underneath all of it; different surfaces, because a tired person needs the format to change even when the science does not.</p>
<p>One detail I am quietly proud of: your memory of a question is keyed to a stable, content-addressed ID, not to the question&#39;s text. Which means I can fix a typo, reorder the curriculum, or add a hundred questions, and nobody&#39;s months of spaced-repetition history get orphaned. The structure protects the guarantee so the product never has to apologize.</p>
<h2>The interface is the physics: how Ascent relates to Fundamental</h2>
<p>Here is the part that is not like other study apps. The entire interface does not sit <em>on top of</em> a background. It is composited <em>inside</em> a running physics simulation.</p>
<p>Fundamental is a particle engine I wrote. In Ascent, one field spans the whole app, and every screen lives within it. The particles are not a looping video or a static gradient; they are simulated, Metal-batched, one draw call each, drifting on a wave field behind everything you touch.</p>
<p>And everything you touch is a <em>body</em> in that field. A button does not rest on the particles; it pushes them. Interactive elements register as deflectors that make particles swirl past. A hero node becomes a vortex that pulls them into slow orbit. A correct answer throws a burst. The motion you see around the interface is the interface&#39;s own physics reacting to itself.</p>
<p>Then the field reads your progress. Its density rises with your exam readiness and climbs a little more with your streak, so when Miranda is deep in a domain she has nearly mastered, the room around the questions is dense and alive, and on a rusty day it is quieter, telling her something before the numbers do. Its palette shifts to the color of whatever domain she is currently working. Break a streak and the whole field contracts to near-black for a couple of seconds before it recovers: a small, wordless acknowledgment that you lost something, with no modal and no badge to shame you about it. The ambience is not decoration. It is a readout of your learning state, rendered in particles.</p>
<p>The discipline underneath it is the same rule again. There are hard budgets: a strict cap on particle density, one draw call per particle, a frame budget the ambience is never allowed to exceed. A beautiful field that costs you a dropped frame on a tap would fail the same honesty test as a comfortable study plan. Ambience that apologizes for itself is worse than none. So the simulation is built to be invisible in exactly the moments it would otherwise get in the way.</p>
<h2>The look: one job per color</h2>
<p>The aesthetic has a name in the codebase, Neon Arcade, and a rule sheet to match: a dark, near-black space, a handful of saturated neon accents, type set entirely in SF Rounded so the interface reads as friendly rather than clinical. But the look is not really about the colors. It is about giving each color exactly one job and never letting it moonlight.</p>
<p>Green means correct: a right answer, a mastered topic, a readiness ring that has crossed into safe territory. Cyan is <em>you</em>: your gem count, your place in the weekly league, the &quot;continue&quot; that carries you forward. Pink is the live challenge: the node you are on right now, the exam you are about to submit, the CAPM itself. Amber is anything in progress or earned: a partial readiness, a flagged question, the streak counter. And red means one thing only. Red is wrong. It appears on an incorrect answer and a failing score and <em>nowhere else</em>: never as a decoration, never as an accent because a screen needed some warmth. In a lot of apps color is mood lighting. Here it is vocabulary, and the most important word in it is the one the app refuses to say unless it means it.</p>
<p>That refusal is the whole design philosophy compressed into a swatch. The interface never cries wolf. When the field collapses to black, you broke a streak. When something turns red, you got it wrong. Nothing on screen is theater; every signal is load-bearing. It is the same honesty as the study plan and the same restraint as the onboarding, expressed in pigment instead of logic. Which is also why the exact same palette, down to the hex values, drives the iOS app, the Android build, and the website. One vocabulary, spoken everywhere, so the app means the same thing no matter where you meet it.</p>
<h2>The game layer, pointed the right way</h2>
<p>A study app with streaks and gems and a daily quest should make you suspicious. Those are precisely the mechanics engagement-farming apps use to manufacture compulsion, and I spent the whole essay so far claiming this one is built on restraint. So it is worth being exact about what they are pointed at.</p>
<p>Miranda earns gems by studying and XP by finishing lessons; a streak counts the days she actually shows up. The one thing gems buy that matters is a streak freeze: you spend what you earned to forgive a single missed day. That is loss aversion turned <em>for</em> the user instead of against them. The mechanic exists to soften the punishment of a bad day, not to weaponize the fear of one into a reason you can&#39;t put the phone down. The daily quest rewards completing study, never merely opening the app. There is no infinite feed, no leaderboard tuned to keep you scrolling, and the single notification is a streak nudge you opted into <em>after</em> your first lesson, not a hook cast at a weak moment.</p>
<p>And there is nothing to milk. The full unlock is one purchase, once. No subscription, no expiry, and the first domain stays free. You <em>can</em> buy a top-up of gems; you never have to, and there is no second charge waiting for you. I will be honest that a gem economy with an optional paid top-up is the one place a reader could reasonably raise an eyebrow, so here is the test I actually held every mechanic to: does it serve Miranda&#39;s deadline, or does it serve a retention metric? Streaks that protect her momentum, a plan that targets her weak spots, an unlock she buys once and owns: those serve the deadline. Anything that only served the metric did not get built. A study app&#39;s honesty is measured on exam day, not in time-on-device, and the whole thing is tuned to the first number.</p>
<h2>The stack, briefly</h2>
<p>For the builders: native SwiftUI, with the whole interface rendered inside a Fundamental field. Metal-batched particles, palette-first, on a strict density and frame budget so the physics never costs the interaction. Content ships from an API with an on-device cache, so a full study session works with no signal at all: the train, the basement, the waiting room, wherever the evening actually happens. Progress lives in a store that merges field by field, tolerant of missing keys, so no sync race and no schema change ever loses a completed lesson. Path progress and spaced-repetition history are both keyed to content-addressed IDs, which is what lets me reorder or expand the 1,122-question curriculum without wiping anyone&#39;s record. Questions come in six formats, true/false through sequencing, and each is worth XP scaled to its cognitive demand, from recall up through application. The same Fundamental engine already runs on Android; the app around it is underway.</p>
<p>The whole thing is built to one rule: the structure enforces the guarantee, so the product does not have to apologize.</p>
<h2>The kicker</h2>
<p>Miranda&#39;s exam is coming up. The app exists because she needed it, and it shipped because a user of one is still a user, with a real deadline, which is more grounding than most product roadmaps ever get.</p>
<p>If someone in your life is staring down the CAPM, it is on the App Store: <a href="https://apps.apple.com/us/app/ascent-capm-prep/id6783151738">Ascent CAPM Prep</a>. Free to start, no account required. That last part is the whole philosophy in four words.</p>
<hr>
<p><strong>Related:</strong> <a href="https://distancefromgray.com">Distance from Gray</a> — the doctrine underneath: derive-don&#39;t-ask is gray reduction on the input side, measuring intent instead of interrogating for it. Site: <a href="https://ascent.guide">ascent.guide</a>.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/i-built-an-app-so-my-lady-could-pass-the-capm">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>IOS</category><category>Product Design</category><category>Systems</category>
    </item>
    <item>
      <title>Living Documentation</title>
      <link>https://zachshallbetter.com/writing/living-documentation</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/living-documentation</guid>
      <pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>The input-side contract for generative work.</description>
      <content:encoded><![CDATA[<p>I wrote recently about <a href="/writing/distance-from-gray">distance from gray</a>: the idea that AI output is unfinished by default, and that value lives in the systems that force it into production-ready form. That essay was about the output side, the contracts that catch gray before it reaches anything downstream. This one is about the input side, because gray does not start at the model. It starts in what you feed it.</p>
<p>Every generative tool works from context. Prompt an assistant with stale architecture notes and it writes code against a system that no longer exists. Point a design tool at last quarter&#39;s terminology and it produces mockups the team has to translate before they can use them. The output looks confident either way. Confidence is what these tools manufacture. Accuracy comes from somewhere else, and that somewhere is the knowledge you handed them.</p>
<p>Most teams handle this the way they handle everything about documentation: a wiki nobody updates, specs that describe the system as it was two refactors ago, tribal knowledge that lives in the heads of whoever has been around longest. That was survivable when humans were the only readers. A person can notice that a document smells stale and go ask someone. A generative tool cannot. It treats whatever you give it as true and builds on it at machine speed. Stale documentation used to produce slow confusion. Now it produces fast, plausible, wrong output in bulk.</p>
<p>Living documentation is the fix. The term has prior art — Cyrille Martraire&#39;s book of the same name made the case for documentation generated from and verified against the working system — and the name means exactly what it says: documentation that is maintained as part of the work, not after it. The current architecture, the real component boundaries, the terminology the team actually uses, the user journeys as they exist today. One source of truth, versioned, updated when the system changes because updating it is part of changing the system.</p>
<p>The payoff shows up in three places.</p>
<p>First, prompts stop lying. When the knowledge base is current, the context you feed a generative tool describes the system that actually exists. The tool still produces probabilistic output, but it is probabilistic output about the right thing. A large share of what gets called hallucination in practice is a model faithfully extrapolating from wrong or outdated context it was given. Fix the input and a whole class of gray never gets generated.</p>
<p>Second, people onboard like the tools do. A new engineer with access to a living knowledge base starts from the same current truth as everyone else. The gap between the newest person and the most senior narrows to judgment and experience, which is where it belongs, instead of access to folklore. I saw this teaching as much as building: students with a real, current reference contribute in week one. Students handed a stale binder spend a month reverse-engineering reality.</p>
<p>Third, iteration stops paying the translation tax. When components, endpoints, and stories are defined and current, a prototype can be checked against the real system the day it is made. Feasibility stops being a meeting and becomes a lookup. The speed generative tools promise only materializes when validation is this cheap, because otherwise every hour the tool saves gets spent verifying what it produced against knowledge someone has to go excavate.</p>
<p>This is also where the speed actually comes from. Everyone selling generative tooling promises prototypes in hours instead of days, and the promise is real, but conditional. The tool is fast because it skips deliberation. If the context it skips to is current, you get a prototype you can validate against the real system the same afternoon: check the endpoints it assumed against the endpoints that exist, check the flow it drew against the journey users actually take. If the context is stale, you get the same prototype at the same speed, and then you spend three days discovering which of its assumptions were archaeology. The tool&#39;s speed is constant. The knowledge base decides whether that speed is progress or just rapidly manufactured rework.</p>
<p>Concretely: a team ships a new feature against a living knowledge base by pulling the current component specs, the personas, and the style guide into the prompt context, generating a first pass, and checking it against documented boundaries the same day. Stakeholders review against the same source, so a correction is an edit to a shared document, not a meeting to reconstruct what the system does. The same team on a stale wiki does the identical generative steps and then loses the week to the gap between what the documentation said and what production does. Same tools, same people, same prompts. The delta is the documentation, which is the point: the documentation is the delta.</p>
<p>The discipline is the hard part, and it is the same discipline as any contract: it only works if it fails closed. Documentation that might be current is documentation that is not current, because nobody can act on might. The rule that makes it living is blunt. If the system changed and the document did not, the change is not done. Teams resist this because it feels like overhead. It is the opposite. The overhead is every downstream consumer, human and machine, independently rediscovering what one update would have recorded.</p>
<p>I build systems that make probabilistic output trustworthy, and I keep finding the same shape on both ends of the pipeline. On the output side, schemas and contracts catch gray before it ships. On the input side, living documentation stops gray from being generated in the first place. Same doctrine, opposite direction: structure is what turns generative capacity into production capability.</p>
<p>The tools will keep getting better at producing output from thin air. The teams that win will be the ones whose air is not thin.</p>
<hr>
<p><strong>Related:</strong> <a href="/writing/distance-from-gray">Distance from Gray</a> — the output-side argument this essay extends.</p>
<p><strong>References:</strong> Cyrille Martraire, <em>Living Documentation: Continuous Knowledge Sharing by Design</em> (Addison-Wesley, 2019). Working systems referenced throughout: <a href="https://github.com/zachshallbetter">github.com/zachshallbetter</a>.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/living-documentation">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>AI</category><category>Documentation</category><category>Systems</category><category>Contracts</category>
    </item>
    <item>
      <title>The Material Is the Contract</title>
      <link>https://zachshallbetter.com/writing/the-material-is-the-contract</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/the-material-is-the-contract</guid>
      <pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>What building a nano-ceramic game board taught me about parameters.</description>
      <content:encoded><![CDATA[<p>The flagship product at Cursed Crypt was a magnetic grid system: a steel game board with a nano-ceramic coating you could write on and wipe clean, holding neodymium-mounted accessories through the surface. Describing it takes one sentence. Building it took mastering six materials that each behaved like an undocumented API, and the education generalized further than any product we shipped.</p>
<p>Here is the thing about materials that nobody tells you until a production run fails: every material has a parameter envelope, and the material does not care whether you know it. Steel, ceramic coating, magnets, ink, resin, adhesive. Each one performs exactly to its physics, every time, and physics does not read your product spec. The work is discovering the envelope before the failure does.</p>
<p>Some of the envelope, concretely, from our floor. Powder coating cures around 200 degrees Celsius; miss the window and the finish goes brittle or peels. Neodymium magnets start losing magnetism above roughly 80 degrees, which means a coated steel part and a magnet cannot pass through the same thermal process, and your production sequence is now a dependency graph. Archival inks bond differently to porous and non-porous surfaces, so the coating decision upstream silently decides which inks are available downstream. Cutting tolerance for parts that must mate magnetically runs to a tenth of a millimeter, and the kerf, the material the blade itself removes, has to be in the math or every piece is systematically small. Surface prep is measured in micrometers of roughness because adhesion is not a property of the glue; it is a property of the interface, and the interface is something you manufacture.</p>
<p>None of these numbers is exotic. Any materials engineer knows them. What made them expensive for us is that they interact, and the interactions are where products die. The nano-ceramic coating that made the board writable had to bond to steel prepared to a specific roughness, cure without reaching the temperature that would have been fine for the steel but fatal to any magnetized component nearby, and produce a surface non-porous enough to wipe clean but receptive enough to print on. Each requirement was satisfiable alone. The product only existed in the intersection.</p>
<p>This is why I keep saying the material is the contract. A contract, in the software sense: a fixed interface you do not negotiate with, you conform to. The material publishes its envelope through its behavior. Your process either respects every clause or fails, and it fails at production scale, on paid-for stock, at the worst available moment. There is no arguing with the 80-degree clause. There is only sequencing around it.</p>
<p>Once you see it that way, the discipline follows the same shape as any contract-driven system.</p>
<p>You characterize before you commit. We tested coating adhesion with scratch and peel tests, magnetic retention with pull-force measurements, dimensions with calipers against defined acceptance thresholds, on a sampling cadence rather than heroic full inspection. Not because a checklist said to, but because a parameter you have not measured is a parameter you are guessing, and a guess embedded in a 25,000-unit run is a very expensive sentence.</p>
<p>You treat unknown behavior as a hard stop, not a fallback. When a new resin or adhesive entered the shop, it got its own characterization pass before it touched a product path. The alternative, assuming the new material behaves like the old one because the datasheet rhymes, is exactly how a whole batch delaminates.</p>
<p>And you document the envelope where the next process can see it, because the person running the printer needs to know the coating decision that was made three steps upstream. Our process notes were the living documentation of the floor: the cure windows, the sequencing constraints, the prep specs. When they were current, a new hire could run a station in days. When they lagged reality, the floor taught the lesson again at material cost.</p>
<p>I build software systems now, and the parallel is not a metaphor, it is the same job. A vendor API has a parameter envelope. A model has one. So does a database under load. The systems that survive are the ones that treat those envelopes as published contracts: characterized before commitment, validated at the boundary, unknown behavior failing hard instead of flowing downstream. The material does not care whether you know its envelope, and neither does the API. Both will execute their physics on your product either way.</p>
<p>The board shipped. It shipped because six materials had their contracts read, respected, and sequenced, and the result looked, to the customer, like one simple object. That is what mastered parameters buy you: all the physics disappears into a thing that just works. The complexity does not go away. It goes into the process, where it belongs.</p>
<hr>
<p><strong>Related:</strong> <a href="/writing/distance-from-gray">Distance from Gray</a> — the same doctrine in software: unmeasured behavior is gray, and contracts are how it becomes production-ready. <a href="/writing/versatility-is-a-design-decision">Versatility Is a Design Decision</a> — how this facility survived COVID.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/the-material-is-the-contract">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Manufacturing</category><category>Systems</category><category>Product</category><category>Contracts</category>
    </item>
    <item>
      <title>Versatility Is a Design Decision</title>
      <link>https://zachshallbetter.com/writing/versatility-is-a-design-decision</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/versatility-is-a-design-decision</guid>
      <pubDate>Thu, 02 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>How a game factory survived COVID by being built for range, not role.</description>
      <content:encoded><![CDATA[<p>When COVID hit, Cursed Crypt should have died. We made premium tabletop gaming products, and tabletop gaming is a business of rooms full of people: conventions, game nights, in-store demos. All of it went dark in the same month. Orders for magnetic grids and miniatures fell off a cliff while the supply chain seized underneath us, materials scarce and shipping costs climbing. A niche manufacturer with one market and no foot traffic is a short obituary.</p>
<p>We survived, and the reason was a decision made years before the virus existed: the facility was never designed to make game products. It was designed to make things, and game products happened to be the things we made.</p>
<p>That distinction sounds like wordplay until you have to live on it.</p>
<h2>What the factory actually was</h2>
<p>Our Spokane Valley facility looked like a game company&#39;s production floor, but every machine in it was chosen for range, not role. The Mutoh 1624X printer earned its place printing game grids, and it was bought because it could print on nearly anything. The Graphtec FC8600 cutter spent its life cutting gaming maps, and it was specced to cut shapes we had no product for yet. The 3D printers, the powder coating rig, the UV coater: each one justified by a current product, selected for the products it could make that we had not thought of.</p>
<p>That is a real cost, and I want to be honest about it. Range is more expensive than fit. A machine specced only for your current product line is cheaper, and a consultant optimizing our capital spending would have flagged half our equipment choices as over-buying. In a stable market, they would have been right.</p>
<p>The market stopped being stable in March 2020.</p>
<h2>The pivot, concretely</h2>
<p>With gaming revenue gone, the same floor started making different things.</p>
<p>Players stuck at home still owned dice, so we used the printers and cutters to produce compact dice boxes and storage, small products for a market that had moved indoors with us. A production company found us and needed film props; the 3D printers and powder coating handled detailed, professional-grade prop work that had nothing in common with miniatures except the machines and the material knowledge. Local businesses needed affordable signage during a period when nobody could afford much, and the Mutoh and Graphtec produced magnetic displays and UV-coated signs durable enough for storefronts.</p>
<p>None of these were in a business plan. All of them ran on equipment bought for games.</p>
<p>The materials told the same story. Magnetic sheet stock, inventoried for tabletop grids, became the base for signage and modular components. The resin supply shifted from miniatures to props, with designs adapted for durability and cinematic detail instead of tabletop scale. Powder coating, developed to give game products a premium finish, turned out to be exactly what film props and commercial work needed. We were not improvising materials. We were re-aiming a materials capability that already existed.</p>
<h2>Why this worked when it should not have</h2>
<p>The standard framing for what happened to us is agility: the plucky company that pivoted fast. I think that framing is wrong, and the difference matters if you are building a production system of your own.</p>
<p>We did not move fast in a crisis. We moved normally, through a system that had slack in its definition. A factory defined as &quot;the thing that makes magnetic game grids&quot; has to be redefined before it can make anything else, and redefinition under pressure, with revenue at zero, is where companies die. A factory defined as &quot;a set of transformation capabilities: print, cut, coat, form&quot; does not need redefinition. It needs new inputs. The pivot was not a heroic act. It was a lookup: what can these machines and these materials produce that someone will pay for this month?</p>
<p>Community was the other half, and it was infrastructure too, not luck. Years of forums, podcasts, and direct customer relationships meant that when the products changed, the audience came along. Grid customers brought us one-off home projects. Word-of-mouth brought the film work. A customer base you actually talk to is a distribution channel that survives a product-line change; a customer base you only sell to is not.</p>
<h2>The design principle</h2>
<p>The lesson I carry from that year is not &quot;be adaptable,&quot; which is advice the way &quot;be rich&quot; is advice. It is that versatility is a property you purchase at design time, at a measurable premium, and cannot buy during the crisis at any price. Every equipment choice, every material we developed deep knowledge of, every capability we built past the needs of the current catalog: those were premiums paid in good years for an option we hoped never to exercise.</p>
<p>We exercised the option in 2020 and it paid for every year of premium at once.</p>
<p>I build software systems the same way now, and it is the same principle wearing different clothes: capabilities over products, general transformation layers under specific offerings, range that looks like over-engineering right up until the market moves. The factory taught me that the system underneath the product is the real asset, because products are what a market lets you sell this year, and capabilities are what you get to sell next year when the market changes its mind.</p>
<p>The game company survived by not being a game company. It was a factory that made games, until the world needed it to make something else.</p>
<hr>
<p><strong>Related:</strong> <a href="/writing/distance-from-gray">Distance from Gray</a> — the doctrine this feeds: value lives in the transformation layer, not the product on top. <a href="/writing/the-material-is-the-contract">The Material Is the Contract</a> — the parameter discipline that ran the same floor.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/versatility-is-a-design-decision">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Manufacturing</category><category>Systems</category><category>Strategy</category><category>Operations</category>
    </item>
    <item>
      <title>Distance from Gray</title>
      <link>https://zachshallbetter.com/writing/distance-from-gray</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/distance-from-gray</guid>
      <pubDate>Fri, 05 Jun 2026 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>Why the next durable layer of AI value is a guarantee, not a generation — and why owning the transformation seam beats managing unreliability at the product layer.</description>
      <content:encoded><![CDATA[<h2>Why the next layer of AI value is a guarantee, not a generation</h2>
<p>Every AI workflow I have seen in production has the same bottleneck, and it is not the model. The output looks right. Nobody can promise it is right. So a human checks it, and the checking costs roughly what the AI saved. Enterprise surveys put the loss at about 37 percent of the time saved. Hallucination rates across even the best models run from 17 to 45 percent depending on domain. In regulated industries, unverifiable output is not an inconvenience. It is prohibited.</p>
<p>I call that state gray.</p>
<h2>What gray is</h2>
<p>Gray is the default state of any unstructured or probabilistic output: variable, hard to audit, not production-ready. A raw LLM response is gray. So is a creative brief, an unparsed web page, a workflow with no governance around it. Gray is not wrong. It is unfinished.</p>
<p>That distinction matters because most people frame AI unreliability as a quality problem, something the next model version will fix. It will not. Better models emit better gray. The variance narrows, the plausibility improves, and the fundamental property stays: you cannot put the output in front of a customer, a regulator, or a downstream system and promise what shape it will take.</p>
<p>A model that is right 95 percent of the time and a model that is right 99 percent of the time have the same production problem. Somebody still has to catch the miss, and the catching does not get cheaper as the model gets better. It arguably gets more expensive, because the misses get harder to spot.</p>
<h2>The wrong layer</h2>
<p>The industry&#39;s default answer is to manage gray at the product layer. Human review steps. Approval flows. Confidence scores in the UI. A thumbs-up button and a feedback loop. This is reasonable product design, and it is the wrong layer for the fix.</p>
<p>Product-layer management accepts gray as a permanent condition and builds furniture around it. Every product in the company rebuilds the same furniture. Every workflow pays the review tax forever. The unreliability never leaves the system. It just gets redecorated.</p>
<p>There is a different place to stand. Between the AI and everything downstream of it, there is a seam where output either becomes trustworthy or does not. Own that seam and the problem stops being managed and starts being eliminated.</p>
<h2>The transformation layer</h2>
<p>The systems I build live at that seam. Each one does exactly one thing: it takes a specific kind of unstructured input and forces it through a hard contract to produce a guaranteed output. Not a better product wrapper around the AI. The layer underneath, where probabilistic becomes deterministic before anything else sees it.</p>
<p>Concretely, a transformation is a bounded conversion with a clear before and after. A raw LLM response, untyped and variable in shape, becomes schema-validated JSON with typed fields that fails closed on invalid output. A hostile, inconsistently structured web page becomes a normalized data object. Raw audio becomes a structured composition plan a renderer can execute. Each transformation is narrow on purpose. Narrow is what makes the guarantee possible.</p>
<p>The mechanics are old-fashioned and that is the point. A stateless service with a strict schema on the way out. Validation on every response. Retries bounded and typed. Unknown input is a hard error, not a best guess. If the model returns something malformed, the transformation layer catches it, not the product, and definitely not the customer.</p>
<p>The precision that keeps this claim honest: this is not deterministic AI. Nobody has that to sell, and anyone who says otherwise is selling gray in a nicer box. This is deterministic contract enforcement around a probabilistic core. The AI can still be wrong. The output can no longer be malformed, untyped, or untraceable. Wrong-but-well-formed is a solvable problem. You can test for it, audit it, and route it. Wrong-and-shapeless is not solvable. It can only be babysat.</p>
<h2>Distance, measured</h2>
<p>If gray is the input state, distance is the measurable improvement once a transformation is applied. I write it as V = Δ. Value equals the delta between input reliability and output reliability.</p>
<p>Writing it that way puts a burden on the builder, which is where the burden belongs. A claim of quality is an opinion. A delta is a measurement. Every system that takes this seriously has to carry its own receipts: how often the raw input would have failed downstream, how often the transformed output actually does, and the gap between those numbers. That gap is the product. Everything else is packaging.</p>
<p>This is also the honest answer to the fair question every infrastructure pitch gets: how do I know this is worth anything? You do not have to trust the answer. You instrument the seam and read it.</p>
<h2>The bet</h2>
<p>Here is the economic argument underneath all of this.</p>
<p>Generation is being commoditized in real time. The cost of producing plausible text, images, code, and audio is collapsing toward zero, and every quarter more of it comes from open models anyone can run. Betting a business on owning generation is betting against gravity.</p>
<p>Guarantee is not being commoditized. The ability to promise that output is schema-valid, auditable, and safe to put in front of a regulator or wire into a production pipeline is scarce now and gets more valuable as generation gets cheaper, because cheaper generation means more gray flooding into more workflows.</p>
<p>Whoever owns the transformation seam owns the bottleneck every serious AI workflow must pass through. Not the most glamorous layer. The load-bearing one.</p>
<p>I have spent twenty years building at exactly this kind of seam: the systems that make other things dependable enough to ship. A factory that turned a tabletop game into 25,000 delivered units. An engine whose two implementations stay honest through machine-checked parity. Pipelines that turn model output into production artifacts with the checking built in, not bolted on. The material changes. The job does not. Take the gray, force it through a contract, and hand downstream something it can trust.</p>
<p>AI made output cheap and trust expensive. The next durable layer of value is the one that makes trust cheap again. That is the distance from gray, and it is the most worthwhile thing I know how to build.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/distance-from-gray">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>Customer Experience (CX) vs. User Experience (UX)</title>
      <link>https://zachshallbetter.com/writing/customer-experience-cx-vs-user-experience-ux</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/customer-experience-cx-vs-user-experience-ux</guid>
      <pubDate>Sat, 18 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>The Intersection of Emotion and Function</description>
      <content:encoded><![CDATA[<p>On a sunny Saturday morning, your favorite neighborhood bakery feels like a haven. The aroma of warm, flaky croissants draws you in, the cashier’s friendly smile welcomes you by name, and the register dings as your loyalty points are automatically updated.</p>
<p>These moments represent the artistry of thoughtful design paired with strategic execution. They illustrate the seamless harmony between <strong>Customer Experience (CX)</strong> and <strong>User Experience (UX)</strong> — two complementary forces shaping how we emotionally and functionally connect with brands. Together, they turn ordinary interactions into extraordinary experiences that resonate long after the moment has passed.</p>
<hr>
<h3>Creating the Magic: Every Interaction Counts</h3>
<p>Let’s unravel the layers of these two experiences and explore where they intersect, how they differ, and how their collaboration can elevate everything from a neighborhood bakery to a global enterprise.</p>
<p>Great businesses don’t just sell products; they create feelings. From the first moment a customer interacts with a brand to the memories they carry forward, every detail matters. Success lies in balancing emotional resonance with practical functionality, crafting a journey where every touchpoint feels intentional and engaging.</p>
<p>Whether it’s an intuitive website that streamlines ordering or a team that greets customers with genuine care, the goal is to blend the warmth of human connection with the efficiency of smart technology. Features like smooth navigation, personalized support, and self-service tools work together to create experiences that elevate both CX and UX, setting the stage for long-term success.</p>
<hr>
<h3>Origins of CX and UX: Building Connections</h3>
<h4>Customer Experience (CX): The journey and emotional connections</h4>
<p>CX emerged in the late 1990s alongside the rise of Customer Relationship Management (CRM) systems. Its foundation, however, lies in <em>The Experience Economy</em>, a groundbreaking concept by Joseph Pine and James Gilmore that shifted focus from simply selling products to creating meaningful experiences.</p>
<p>CX encompasses the <strong>entire customer journey</strong> — from discovery to loyalty. Successful CX strategies incorporate key elements such as:</p>
<ul>
<li><p><strong>Convenience:</strong> Speed and ease across touchpoints.</p>
</li>
<li><p><strong>Connectivity:</strong> Seamless interactions on preferred customer channels.</p>
</li>
<li><p><strong>Personalization:</strong> Tailored experiences that resonate emotionally.</p>
</li>
</ul>
<p>Tools like customer journey mapping and data analytics have become essential for businesses to refine these touchpoints. By analyzing how customers navigate digital and physical spaces, companies uncover both bottlenecks and unexpected delights, enabling them to craft better, more connected experiences.</p>
<p>For detailed guidance on crafting superior CX strategies, check out <a href="https://www.nngroup.com/articles/customer-journey-mapping/">NNGroup’s guide to Customer Journey Mapping</a>.</p>
<h4>User Experience (UX): Functional and intuitive interactions</h4>
<p>UX, born from the design world, was coined by Don Norman, who emphasized the importance of usability, clarity, and efficiency. His book, <a href="https://www.jnd.org/books/the-design-of-everyday-things-revised-and-expanded-edition.html">The Design of Everyday Things</a>, remains a cornerstone for understanding how thoughtful design enhances satisfaction and ease of use.</p>
<p>Effective UX strategies often include:</p>
<ul>
<li><p><strong>Mobile-First Design:</strong> Optimizing for small screens and touch interactions.</p>
</li>
<li><p><strong>AI-Driven Personalization:</strong> Predicting user needs based on past behaviors.</p>
</li>
<li><p><strong>Accessibility:</strong> Making interfaces usable for all demographics.</p>
</li>
</ul>
<p>For an in-depth exploration of foundational UX principles, visit the <a href="https://www.interaction-design.org/literature/topics/ux-design">Interaction Design Foundation</a>.</p>
<h3>Defining the Relationship: Crafting CX and UX</h3>
<h4>Customer Experience (CX)</h4>
<p>CX refers to the <strong>totality of every interaction</strong> a customer has with a brand, including emotional impressions and long-term perceptions. Successful CX strategies leverage technology like CRM systems to collect and analyze customer data, providing actionable insights for enhancing engagement.</p>
<ul>
<li><p><strong>Scope:</strong> Covers every interaction across all channels and touchpoints.</p>
</li>
<li><p><strong>Goal:</strong> Build emotional connections that foster loyalty and advocacy.</p>
</li>
<li><p><strong>Metrics:</strong> Net Promoter Score (NPS), Customer Satisfaction (CSAT), and loyalty rates.</p>
</li>
</ul>
<h4>User Experience (UX)</h4>
<p>UX zeroes in on how well an individual product or system functions. It’s about reducing friction and ensuring users can achieve their goals effortlessly.</p>
<ul>
<li><p><strong>Scope:</strong> Focuses on specific interactions with a product or service.</p>
</li>
<li><p><strong>Goal:</strong> Make every interaction intuitive, efficient, and user-friendly.</p>
</li>
<li><p><strong>Metrics:</strong> Task completion rates, error rates, and usability scores.</p>
</li>
</ul>
<h3>Contrasting Layers: CX vs. UX</h3>
<h4>Scope</h4>
<ul>
<li><p><strong>CX:</strong> A broad, holistic approach spanning the entire brand experience.</p>
</li>
<li><p><strong>UX:</strong> A narrower focus on individual touchpoints, like a website or app.</p>
</li>
</ul>
<h4>Goals</h4>
<ul>
<li><p><strong>CX:</strong> Build trust, loyalty, and long-term emotional bonds.</p>
</li>
<li><p><strong>UX:</strong> Ensure usability, efficiency, and satisfaction at specific points.</p>
</li>
</ul>
<h4>Metrics</h4>
<ul>
<li><p><strong>CX:</strong> Measures satisfaction and emotional engagement.</p>
</li>
<li><p><strong>UX:</strong> Tracks functional success and user efficiency.</p>
</li>
</ul>
<h4>Emotional vs. Functional</h4>
<ul>
<li><p><strong>CX:</strong> Seeks to delight customers emotionally.</p>
</li>
<li><p><strong>UX:</strong> Prioritizes functional ease and usability.</p>
</li>
</ul>
<h3>Synergy: How CX and UX Work Together</h3>
<p>CX and UX thrive in synergy, each amplifying the other’s impact. A well-designed app (UX) can elevate how customers perceive a brand (CX), but even the most seamless design can be undermined by a poor overall experience, like delays or unresponsive support.</p>
<h4><strong>CX in Action:</strong></h4>
<ul>
<li><p>A customer discovers a social media ad for your brand’s seasonal specials.</p>
</li>
<li><p>They visit a physical store, where a staff member greets them warmly and offers personalized recommendations.</p>
</li>
<li><p>Post-purchase, they receive a thank-you email with a discount for their next visit.</p>
</li>
</ul>
<h4><strong>UX in Action:</strong></h4>
<ul>
<li><p>The website is intuitive, letting customers and place orders in seconds.</p>
</li>
<li><p>Loyalty points are automatically applied during checkout.</p>
</li>
<li><p>Real-time order tracking is available with a single click.</p>
</li>
<li><p>Fields are pre-populated with their information</p>
</li>
</ul>
<h3>Why CX and UX Must Align</h3>
<p>Brands like Apple, Amazon, and Tesla succeed by seamlessly aligning CX and UX. Apple pairs sleek product design (UX) with exceptional in-store experiences (CX). Amazon’s one-click purchasing (UX) is bolstered by fast, reliable shipping and hassle-free returns (CX). Tesla’s intuitive car systems (UX) reinforce direct customer relationships and continuous updates (CX).</p>
<p>To thrive in competitive markets, businesses must excel in both areas, ensuring every layer of the customer journey is cohesive and impactful. Learn more from <a href="https://www.nngroup.com/articles/ux-strategy/">NNG’s article UX and CX Merge</a>.</p>
<h3>Shaping the Future: CX and UX Convergence</h3>
<p>As technology evolves, CX and UX are converging. Modern customers expect <strong>omnichannel experiences</strong> — seamlessly transitioning between in-store, online, and mobile interactions. Personalization driven by <strong>AI</strong> and <strong>voice-controlled interfaces</strong> continues to blur the lines between the emotional and functional aspects of brand experiences.</p>
<h4>Looking Forward</h4>
<ul>
<li><p><strong>Customer Experience (CX):</strong> Cultivate loyalty through memorable journeys.</p>
</li>
<li><p><strong>User Experience (UX):</strong> Optimize touchpoints for efficiency and ease.</p>
</li>
</ul>
<h3>Experiences That Endure</h3>
<p>In total, view CX and UX as the strategies, art, and science of creating connections. Beneath these concepts lie disciplines like <strong>Service Design</strong>, <strong>Journey Mapping</strong>, and <strong>Experience Analytics</strong>, which serve as the foundation for crafting cohesive and impactful engagements.</p>
<p>The best businesses understand that every interaction, whether it’s a personal greeting or a seamless app experience, is a chance to build trust and loyalty. By balancing emotion and functionality, brands can transform fleeting moments into lasting impressions, ensuring customers feel both valued and understood.</p>
<p>Mastering CX and UX isn’t just about meeting expectations — it’s about creating experiences that endure. For further insights, explore <a href="https://www.interaction-design.org/literature/topics/service-design">IDF’s comprehensive guide to Service Design</a>.</p>
<p>If you’re interested in delving deeper into this topic, <a href="https://www.nngroup.com/articles/ux-vs-cx/%5C">NNGroup’s article User Experience vs. Customer Experience: What’s The Difference?</a> offers expert insights that are highly regarded in the field. Their expertise in crafting and analyzing experiences makes this resource a must-read.</p>
<p>If you’re interested in delving deeper into this topic, NNGroup’s article User Experience vs. Customer Experience: What’s The Difference? offers expert insights that are highly regarded in the field. Their expertise in crafting and analyzing experiences makes this resource a must-read for professionals aiming to master CX and UX.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/customer-experience-cx-vs-user-experience-ux">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Life</category><category>Ux</category><category>Project management</category><category>Technology</category><category>Design</category>
    </item>
    <item>
      <title>Shit Does Not Roll Downhill, It Gets Tracked Everywhere</title>
      <link>https://zachshallbetter.com/writing/shit-does-not-roll-downhill-it-gets-tracked-everywhere</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/shit-does-not-roll-downhill-it-gets-tracked-everywhere</guid>
      <pubDate>Tue, 14 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>Redefine Leadership Through Accountability and Team Resilience</description>
      <content:encoded><![CDATA[<p>There’s a reason the saying “<strong>shit rolls downhill</strong>” persists in corporate culture, symbolizing the tendency for leadership challenges to cascade downwards, often leaving teams to bear the brunt without accountability at the top. Yet in today’s hyperconnected workplace, problems don’t just roll downhill; they ripple through every level of the organization, leaving behind a trail of inefficiencies and unresolved tensions.</p>
<p>Missed deadlines, miscommunications, and rising turnover are not isolated phenomena. They’re often symptoms of deeper, systemic issues — ones that can be traced to decisions made, or avoided, at the leadership level. In an age of project management dashboards, real-time messaging, and performance analytics, nothing stays hidden for long. Leaders who deflect responsibility leave behind a trail of operational chaos, undermining trust and team cohesion.</p>
<p>Leadership accountability, therefore, is not optional. It is foundational to building resilient teams and fostering a culture of growth and collaboration. This article explores how leaders can break the cycle of blame, own their role in problem-solving, and inspire their teams to do the same.</p>
<h3><strong>The Fallout of Avoidance</strong></h3>
<p>When leaders pass problems down the chain of command without resolving them, the fallout is immediate and far-reaching, creating a ripple effect that compromises team dynamics. Repeated instances of leadership deflection breed mistrust, lower morale, and increase disengagement. Teams become less inclined to communicate openly or share innovative ideas, fearing their concerns will be dismissed or mishandled. Over time, this erodes cohesion and fosters a defensive work culture where individuals focus on self-preservation rather than collaboration.</p>
<p>For example, consider a high-pressure sales environment where leadership consistently shifts blame for missed quotas onto frontline employees. Over time, this deflection leads to decreased productivity, higher turnover rates, and an inability to retain high performers. Trust, once eroded, takes significant effort to rebuild, highlighting the long-term consequences of unresolved leadership issues.</p>
<p>This scenario creates a cascading effect. Frustration grows as team members scramble to realign. Communication breaks down as assumptions replace clarity. Deadlines slip, and tensions rise. By the time leadership revisits the project, trust has eroded, and morale has plummeted.</p>
<p>These ripple effects reveal three critical areas of impact. First, on team dynamics, where unresolved issues foster resentment and disengagement. Second, on organizational culture, where repeated deflection breeds distrust in leadership. And third, on operational efficiency, where inefficiencies and delays derail even well-planned initiatives. Avoidance doesn’t resolve problems; it multiplies them.</p>
<h4>Recognizing the Fallout of Unmanaged Issues</h4>
<p>What Happens When Problems Are Mismanaged?</p>
<ul>
<li><p><strong>Team Impact:</strong> Issues that are ignored or poorly handled create unnecessary burdens for the team, leading to frustration and decreased morale.</p>
</li>
<li><p><strong>Cultural Erosion:</strong> Teams learn to distrust leadership when problems are consistently ‘passed down’ without acknowledgment or resolution, a behavior that eventually shapes organizational culture. A culture of deflection stifles innovation by discouraging risk-taking and experimentation — core elements of a thriving workplace. Employees may become hesitant to propose bold ideas or challenge the status quo, fearing that any missteps will result in blame rather than constructive feedback. Moreover, the long-term effects on employee retention are profound. According to a Gallup study, workplaces with low accountability report a 22% higher turnover rate and diminished employee advocacy. When leadership avoids responsibility, they not only compromise current operations but also erode the foundation for future growth and talent acquisition.</p>
</li>
<li><p>**Operational Chaos:**Mismanaged problems leave behind a trail of inefficiencies, delays, and miscommunications.</p>
</li>
</ul>
<h3><strong>Why Leaders Must Take Responsibility</strong></h3>
<p>Leadership begins with accountability. Owning a problem, rather than deflecting blame, sets the stage for collaborative problem-solving and cultural resilience. Far from signaling weakness, accountability demonstrates integrity and builds trust.</p>
<p>Consider the contrast between a leader who says, “I understand that changing priorities caused confusion, and I’ll clarify our goals,” versus one who says, “The team should’ve known how to adapt.” The former creates psychological safety and encourages transparency. The latter fosters defensiveness and disengagement.</p>
<p>Accountability also prevents problems from escalating. By addressing issues early, leaders can resolve small challenges before they evolve into major crises. This proactive approach minimizes disruption and ensures teams remain focused on their objectives.</p>
<h3><strong>Leadership Principles for Accountability</strong></h3>
<h4>Acknowledge the Problem</h4>
<p>The first step in resolving any issue is recognizing its existence. Leaders who address problems head-on create an environment where challenges are seen as opportunities for growth.</p>
<ul>
<li><p><strong>What to Do:</strong> Call out the problem directly in team discussions or one-on-one settings. Be the first and last to address it.</p>
</li>
<li><p><strong>What to Avoid:</strong> Blaming external factors or individuals without introspection, especially in front of others.</p>
</li>
<li><p><strong>Example:</strong> “I realize our priorities shifted suddenly, and it’s caused confusion. Let’s clarify and make adjustments.?”</p>
</li>
</ul>
<h4>Set the Standard for Accountability</h4>
<p>Leadership accountability sets the tone for how the team approaches responsibility. Transparency at the top fosters a culture where everyone feels empowered to own their contributions.</p>
<ul>
<li><p><strong>What to Do:</strong> Share your mistakes openly and outline how you’re addressing them.</p>
</li>
<li><p><strong>What to Avoid:</strong> Dodging responsibility or deflecting blame to others.</p>
</li>
<li><p><strong>Example:</strong> “I miscalculated the time needed for this phase of the project, and I’ll work with you to adjust timelines.”</p>
</li>
</ul>
<h4><strong>Focus on Root Causes, Not Quick Fixes</strong></h4>
<p>Quick fixes may alleviate immediate symptoms but rarely address the underlying problem. Leaders who prioritize root cause analysis not only resolve current challenges but also prevent similar issues from recurring. For instance, Toyota’s implementation of the ‘Five Whys’ method — a core principle of its Lean manufacturing system — demonstrates how digging deeper into problems fosters sustainable improvement. By repeatedly asking ‘why’ until the root cause of an issue is identified, Toyota has minimized production bottlenecks and improved overall efficiency. This proactive approach to leadership ensures that solutions are comprehensive, fostering a culture of continuous learning and adaptability.</p>
<ul>
<li><p><strong>What to Do:</strong> Focus on root cause analysis to prevent similar issues in the future.</p>
</li>
<li><p><strong>What to Avoid:</strong> Quick fixes that push the problem downstream.</p>
</li>
<li><p><strong>Example:</strong> If team burnout is rising, investigate workload distribution and adjust priorities.</p>
</li>
</ul>
<h3><strong>A Collaborative Approach to Leadership</strong></h3>
<p>One of the most destructive habits in leadership is deflecting responsibility. Blaming external factors, other departments, or individual contributors may offer temporary relief, but it does nothing to address the root cause. Worse, it erodes trust and reinforces a culture of finger-pointing.</p>
<p>Effective leaders take a collaborative approach to problem-solving. They view challenges as opportunities to refine processes, improve communication, and foster innovation. By addressing issues head-on and involving their teams in the resolution process, they strengthen organizational resilience and adaptability.</p>
<h4><strong>Normalize Transparency</strong></h4>
<p>Encourage open discussions about challenges at every level. Regular retrospectives and post-mortems can help identify lessons learned and areas for improvement.</p>
<ul>
<li><p><strong>How to Do It:</strong> Hold problem-solving sessions where team members feel safe discussing issues.</p>
</li>
<li><p><strong>Example:</strong> “What went well, and what can we improve for the next sprint?</p>
</li>
</ul>
<h4><strong>Establish Clear Escalation Paths</strong></h4>
<p>When issues arise, they should flow upstream for resolution, not downstream for avoidance.</p>
<ul>
<li><p><strong>How to Do It:</strong> Define clear processes for escalating challenges to leadership.</p>
</li>
<li><p><strong>Example:</strong> “If you encounter a roadblock, escalate it to me immediately so we can resolve it quickly.”</p>
</li>
</ul>
<h4><strong>Reward Initiative</strong></h4>
<p>Celebrate team members who proactively identify and address problems. Recognition reinforces a solution-oriented mindset and encourages others to do the same.</p>
<h4><strong>Foster a Solution-Oriented Culture</strong></h4>
<p>Accountable leadership lays the groundwork for a solution-oriented culture. When teams see leaders addressing challenges constructively, they feel empowered to contribute their insights and solutions.</p>
<p>Foster transparency by encouraging open discussions about challenges. Use retrospectives and post-mortems to analyze setbacks and identify opportunities for improvement. Establish clear escalation paths so unresolved issues flow upward for resolution, not downward for deflection. And most importantly, reward initiative. Celebrate team members who proactively identify and address problems.</p>
<h3><strong>Conclusion: Leadership Beyond Deflection</strong></h3>
<p>The idea that “shit rolls downhill” reflects an outdated and ineffective approach to leadership. True accountability doesn’t flow downhill — it starts at the top. Leaders who take ownership of their decisions, address challenges proactively, and foster transparency build trust, resilience, and collaboration.</p>
<p>In modern organizations, where visibility into workflows and outcomes is unparalleled, deflection and avoidance are not viable strategies. The real test of leadership lies in how effectively problems are acknowledged and resolved. By embracing accountability, leaders create environments where teams feel empowered, supported, and aligned toward common goals.</p>
<p>Leadership is not about passing blame. It’s about stepping up, owning the responsibility, and driving meaningful, lasting progress. In this approach lies the foundation for sustainable growth, high-performing teams, and a resilient organizational culture</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/shit-does-not-roll-downhill-it-gets-tracked-everywhere">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Productivity</category><category>Leadership</category><category>Product management</category><category>Business</category><category>Management</category>
    </item>
    <item>
      <title>The Grounds of First Principles</title>
      <link>https://zachshallbetter.com/writing/the-grounds-of-first-principles</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/the-grounds-of-first-principles</guid>
      <pubDate>Mon, 13 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>From Root Assumptions to Refined Solutions</description>
      <content:encoded><![CDATA[<p><strong>Most professionals go through their careers working within frameworks, processes, or “best practices” that someone else designed.</strong> They inherit rules about how things should be done — how products are made, problems are solved, or meetings are run — and often follow those rules without question. But what happens when the rules don’t work?</p>
<p>This is where first principles thinking comes in. It’s the mental model that strips away assumptions and asks, <em>“What are the fundamental truths at play here?”</em> It’s not just a tool for science or engineering — it’s a framework for everything: from designing better products to building stronger teams to solving problems that feel unsolvable.</p>
<h3><strong>What Are First Principles?</strong></h3>
<p>First principles are the fundamental building blocks of knowledge — basic, self-evident truths that cannot be deduced from anything else. This concept, originating in ancient philosophy, serves as the bedrock for reasoning and problem-solving across disciplines. Instead of relying on reasoning by analogy — where decisions are based on how similar problems have been handled before — first principles thinking strips a problem down to its core truths and builds solutions from the ground up.</p>
<h4><strong>They are defined by these three ideas.</strong></h4>
<ul>
<li><p><strong>Identify</strong>: Break the problem down to its most fundamental truths.</p>
</li>
<li><p><strong>Question</strong>: Challenge assumptions and conventions.</p>
</li>
<li><p><strong>Ground</strong>: Rebuild solutions from the core truths.</p>
</li>
</ul>
<p>The roots of first principles thinking stretch back to Aristotle, who wrote in <em>Metaphysics</em>: **“In every systematic inquiry (whether in art, or in science, or in any other intellectual pursuit), there are certain points which must be admitted from the outset, and these are the first principles.”**His focus was on identifying the fundamental truths that underpin all knowledge and inquiry, making it possible to reason logically and systematically.</p>
<p>Fast forward to modern times, and first principles thinking has been popularized (years ago) by innovators like Elon Musk, who credits this method with allowing him to disrupt industries ranging from electric vehicles to space travel. Musk explained his approach in a 2012 interview, saying: “I tend to approach things from a physics framework. Physics teaches you to reason from first principles rather than by analogy. So, I said, ‘Okay, what are the material costs of the raw materials in a battery? What would it cost to buy them on the London Metal Exchange?’ It turned out that it was just 2% of what a finished battery pack cost.” This insight helped Tesla dramatically reduce battery costs and gain a competitive edge.</p>
<blockquote>
<p>To clarify, while Elon Musk is often cited as a modern practitioner of first principles thinking, this article isn’t an endorsement of him or his leadership style. His use of this mental framework is one example among many, but first principles thinking has a rich history that predates his work and extends far beyond any single individual. My focus is on the power of this approach, not the personalities associated with it. This distinction is important to separate the value of the concept from any one person’s interpretation or actions. I’ll refer to SpaceX from here forward when convering these concepts.</p>
</blockquote>
<p>Luckily, first principles thinking isn’t limited to philosophy or groundbreaking technology. It can be applied in day-to-day problem-solving, leadership, and decision-making. Whether designing a new product, troubleshooting a workflow bottleneck, or reimagining a team structure, this method enables individuals and organizations to challenge assumptions, simplify complexity, and uncover opportunities for innovation.</p>
<p>At its core, first principles thinking asks us to confront assumptions head-on: Why do we do things this way? What are we trying to achieve? What’s the simplest, most effective path forward? By answering these questions, we free ourselves from the constraints of “how it’s always been done” and open the door to transformative ideas and solutions.</p>
<p>Ultimately, first principles thinking provides a framework for clarity in a world that often defaults to complexity. It’s a tool not just for visionaries like Aristotle but for anyone looking to break down barriers, innovate, and make better decisions.</p>
<h3><strong>First Principles in Practice: Rethinking the Morning Coffee Routine</strong></h3>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/the-grounds-of-first-principles/c0bc4f7339cc3ceb.png" alt=""></p>
<p>Let’s take a simple, everyday scenario: making your morning coffee. Most people follow a familiar process because “that’s just how it’s done” — buying pre-ground coffee, using a standard coffee maker, and adding store-bought cream and sugar. But what happens when we apply first principles thinking to this routine?</p>
<p>First, break the process down to its core purpose: <strong>The goal is to enjoy a fresh, flavorful cup of coffee to start the day.</strong> Everything else — how the coffee is brewed, what kind of beans are used, and how it’s flavored — is open to rethinking.</p>
<h4><strong>1. Identify the foundational truths:</strong></h4>
<ul>
<li><p>Coffee flavor comes from freshly ground beans.</p>
</li>
<li><p>Brewing methods influence the taste, from smoothness to strength.</p>
</li>
<li><p>Additives like cream and sugar mask or enhance specific flavors.</p>
</li>
</ul>
<h4><strong>2. Question assumptions:</strong></h4>
<ul>
<li><p>Do you need an expensive coffee maker, or could a simpler method (like a French press or pour-over) produce better results?</p>
</li>
<li><p>Does coffee have to be pre-ground? Would grinding it fresh improve the flavor?</p>
</li>
<li><p>Is sugar necessary, or could you experiment with different beans that naturally taste sweeter or nuttier?</p>
</li>
</ul>
<h4><strong>3. Rebuild from the ground up:</strong></h4>
<ul>
<li><p>Buy whole beans and invest in a small grinder to ensure the freshest flavor.</p>
</li>
<li><p>Experiment with brewing methods, like a French press or AeroPress, to find the best extraction for your taste.</p>
</li>
<li><p>Try different bean varieties — Ethiopian for fruity notes, Brazilian for chocolate undertones — and ditch the sugar for natural flavor discovery.</p>
</li>
</ul>
<h4><strong>The Outcome</strong></h4>
<h4><strong>The Broader Lesson</strong></h4>
<p>This example highlights how first principles thinking can uncover better, simpler solutions by challenging assumptions — even in something as mundane as your morning coffee. It’s a reminder that first principles can apply to all aspects of life, not just complex systems or groundbreaking innovations.</p>
<h4>Advanced Mode</h4>
<p>Once you’ve reimagined your coffee routine by applying the basic principles, you can push the boundaries even further. Let’s explore how a deeper dive into first principles can elevate your coffee experience to an entirely new level.</p>
<h4><strong>1. Optimize Bean Selection Through Science</strong></h4>
<ul>
<li><p><strong>Identify</strong>: The chemical composition of coffee beans influences flavor. Factors like roast level, bean origin, and processing methods (washed, natural, or honey-processed) play a role in taste and aroma.</p>
</li>
<li><p><strong>Question</strong>: Are you choosing beans based solely on popularity or brand reputation? Could experimenting with fermentation methods or micro-lot beans provide more nuanced flavors?</p>
</li>
<li><p><strong>Ground</strong>: Research the science behind bean varieties (Arabica vs. Robusta), and experiment with rare or experimental coffees, such as anaerobic fermentation or geisha varietals.</p>
</li>
</ul>
<h4><strong>2. Master the Brewing Variables</strong></h4>
<ul>
<li><p><strong>Identify</strong>: Brewing temperature, grind size, water-to-coffee ratio, and brew time all significantly affect the final cup.</p>
</li>
<li><p><strong>Question</strong>: Are you brewing at an arbitrary temperature, or could precision improve your results? Is your water quality affecting the flavor?</p>
</li>
<li><p><strong>Ground</strong>: Use a digital scale for precise measurements, a temperature-controlled kettle, and filtered water to control every variable. Fine-tune these elements to match the flavor profile you desire.</p>
</li>
</ul>
<h4><strong>3. Explore Sustainable and Ethical Practices</strong></h4>
<ul>
<li><p><strong>Identify</strong>: Coffee production impacts the environment and communities. Sustainable practices can enhance both the flavor and the ethical footprint of your cup.</p>
</li>
<li><p><strong>Question</strong>: Are your beans sourced from farms practicing fair trade and eco-friendly farming methods? Could supporting local roasters reduce your carbon footprint?</p>
</li>
<li><p><strong>Ground</strong>: Research coffee cooperatives or small-scale farmers who focus on sustainable and ethical practices. Purchase from roasters who prioritize direct trade and transparent sourcing.</p>
</li>
</ul>
<h4><strong>4. Engineer Your Own Brewing Gear</strong></h4>
<ul>
<li><p><strong>Identify</strong>: Store-bought coffee makers may limit your ability to control brewing variables.</p>
</li>
<li><p><strong>Question</strong>: Could custom or DIY brewing tools better suit your personal coffee preferences?</p>
</li>
<li><p><strong>Ground</strong>: Experiment with modifying existing brewing equipment or design your own. For example, use 3D printing to create custom filter holders or flow restrictors for more precise extraction.</p>
</li>
</ul>
<h4><strong>5. Optimize Energy Efficiency in the Brewing Process</strong></h4>
<ul>
<li><p><strong>Identify</strong>: Brewing methods consume varying levels of energy, from electric machines to manual presses.</p>
</li>
<li><p><strong>Question</strong>: Could you reduce your environmental impact by switching to a more energy-efficient process?</p>
</li>
<li><p><strong>Ground</strong>: Analyze the energy consumption of each method and experiment with manual brewing techniques, like a hand grinder paired with a non-electric pour-over system.</p>
</li>
</ul>
<h3>First Principles in Practice: <strong>Rethinking the Cost of Space Exploration</strong></h3>
<p>One of the more compelling examples of first principles thinking comes from Elon Musk and SpaceX, where it has been applied to revolutionize the economics of space exploration. Historically, space travel was extraordinarily expensive. Governments and agencies like NASA relied on single-use rockets, with launch costs running into hundreds of millions of dollars. This high price tag was largely accepted as a given — “that’s just how it’s always been.”</p>
<p>Musk approached the problem differently. Instead of reasoning by analogy and accepting the status quo, he broke the challenge down to its fundamental components. He asked: What are rockets actually made of? Why are they so expensive?</p>
<h4><strong>Applying First Principles</strong></h4>
<h4><strong>1. Identify the foundational truths:</strong></h4>
<ul>
<li><p>Rockets are primarily made from aluminum alloys, carbon fiber, and a few rare metals.</p>
</li>
<li><p>The core cost of these raw materials is only a fraction of the total price of building and launching a rocket.</p>
</li>
<li><p>• Space missions typically rely on single-use rockets, significantly driving up costs.</p>
</li>
</ul>
<h4>2. <strong>Question assumptions:</strong></h4>
<ul>
<li><p>Do rockets need to be single-use? Could they be designed to land, be refurbished, and launched again?</p>
</li>
<li><p>Is it necessary to outsource or purchase pre-manufactured components at premium prices, or can they be built in-house?</p>
</li>
<li><p>Could automation and streamlined manufacturing processes reduce labor and production costs?</p>
</li>
</ul>
<h4>3. <strong>Rebuild from the ground up:</strong></h4>
<ul>
<li><p>SpaceX invested in developing reusable rockets, such as the Falcon 9, capable of landing back on Earth for refurbishment and relaunch.</p>
</li>
<li><p>By manufacturing rocket components in-house, SpaceX eliminated reliance on costly third-party suppliers.</p>
</li>
<li><p>The company innovated in materials science, using lighter yet stronger materials, and developed cost-effective assembly techniques.</p>
</li>
</ul>
<h4><strong>The Outcome</strong></h4>
<p>The results were transformative. SpaceX’s breakthrough in reusable rockets reduced the cost of launching payloads into orbit by as much as 70%. A Falcon 9 rocket now costs around $67 million per launch, compared to the $500 million launches of traditional space programs. By starting with first principles, SpaceX not only cut costs but also increased the frequency and reliability of launches, helping to reinvigorate global interest in space exploration.</p>
<h4><strong>The Broader Lesson</strong></h4>
<p>This example demonstrates the power of first principles to challenge entrenched norms and drive innovation in even the most established industries. Musk’s approach didn’t just make rockets more affordable; it transformed the entire business model of space travel, making it accessible to more organizations and even paving the way for future commercial spaceflight.</p>
<p>The implications of this mindset extend far beyond the aerospace industry. By applying first principles to cost structures, workflows, or product designs, companies in sectors such as manufacturing, logistics, and energy can identify opportunities to streamline operations, reduce inefficiencies, and solve problems that once seemed insurmountable.</p>
<h3><strong>How These Ideas Can Be Applied Across Domains</strong></h3>
<p>First principles are universal. No matter the field, the same fundamental approach can provide clarity, spark creativity, and create meaningful change.</p>
<h4><strong>People and Teams</strong></h4>
<p>People are often seen as the most complex part of any organization, but at their core, all humans share basic needs and motivations: respect, purpose, autonomy, and connection.</p>
<ul>
<li><p><strong>Building Culture:</strong> Focus on respect, autonomy, and purpose.</p>
</li>
<li><p><strong>Managing Teams:</strong> Design around unique strengths instead of rigid hierarchies.</p>
</li>
</ul>
<h4><strong>Products (Digital and Physical)</strong></h4>
<p>Great products solve real problems, but they’re often weighed down by unnecessary complexity or features added “just because.”</p>
<ul>
<li><p><strong>Start with the Problem:</strong> Solve real issues without unnecessary features.</p>
</li>
<li><p><strong>Eliminate Assumptions:</strong> Reevaluate processes and materials for better solutions.</p>
</li>
</ul>
<h4><strong>Marketing and Messaging</strong></h4>
<p>Marketing can feel formulaic — A/B tests, funnels, and strategies pulled from playbooks. But when you strip it back, all marketing boils down to one question: <em>How do we connect with people?</em></p>
<ul>
<li><p><strong>Understand the Audience:</strong> Focus on needs, fears, and desires.</p>
</li>
<li><p><strong>Simplify the Message:</strong> Communicate with clarity and impact.</p>
</li>
</ul>
<h4>Problem-Solving and Troubleshooting</h4>
<p>Most troubleshooting efforts start by fixing symptoms. First principles thinking forces you to look deeper, asking: What is the root cause?</p>
<ul>
<li><p><strong>Identify Root Causes</strong>: Solve the actual problem instead of symptoms.</p>
</li>
<li><p><strong>Question assumptions:</strong></p>
</li>
<li><p>**Rebuild from the ground up:**Isolate the core and trace the symptoms</p>
</li>
</ul>
<h4>Learning and Growth</h4>
<p>When learning new skills or exploring new fields, it’s easy to get overwhelmed by jargon or preconceived ideas. First principles help simplify the process.</p>
<ul>
<li><p><strong>Focus on Fundamentals:</strong> Master the basics before layering complexity.</p>
</li>
<li><p>**Question the Rules:**Just because something is taught as “the way” doesn’t mean it’s the only way.</p>
</li>
</ul>
<h4>Meetings and Collaboration</h4>
<p>Meetings often feel like a necessary evil, but they don’t have to. By applying first principles, you can design better ways to collaborate.</p>
<ul>
<li><p><strong>Ask Why:</strong> Redesign meetings with clear goals.</p>
</li>
<li><p><strong>Reimagine Formats:</strong> What would a meeting change if built from scratch</p>
</li>
</ul>
<h4>Experience and Empathy</h4>
<p>Whether designing customer experiences or managing relationships, first principles help you focus on what matters most: understanding people.</p>
<ul>
<li><p><strong>Customer Experience</strong>: Streamline journeys and focus on clarity.</p>
</li>
<li><p><strong>Empathy in Leadership</strong>: Understand emotions to build trust.</p>
</li>
</ul>
<h4>Why First Principles Matter More Than Ever</h4>
<p>Our world thrives on rapid change and increased complexity. Your understanding of first principles is a superpower, a way to innovate without being constrained by “how it’s always been done.”</p>
<p>For individuals, adopting this mindset creates opportunities for growth, leadership, and impact. It allows you to question, challenge, and improve everything you touch.</p>
<h3>Finally, a Few Formulas to Consider</h3>
<p>The following formulas show how these principals simplify complexity by focusing on core components and addressing each foundational element individually.</p>
<h4>Cost Optimization in Product Design</h4>
<p><strong>Total Cost = Material Cost + Manufacturing Cost + Distribution Cost</strong>this formula into components, you can analyze and reduce costs in each area.</p>
<h4>Energy Efficiency in Engineering</h4>
<p><strong>Energy Output = Energy Input — Energy Loss</strong>Break Energy Loss into heat, friction, or inefficiencies to improve system performance.</p>
<h4><strong>Problem-Solving Framework</strong></h4>
<p><strong>Problem = Constraints + Resources + Desired Outcome</strong>Focus on isolating constraints, leveraging resources, and clarifying goals to simplify complex challenges.</p>
<h4>Decision-Making Formula</h4>
<p><strong>Outcome = (Probability of Success × Potential Impact) — Cost of Failure</strong>Evaluate decisions based on their expected value to minimize risk and maximize potential.</p>
<h4>Skill Acquisition Formula</h4>
<p>**Skill Mastery = Core Fundamentals × (Repetition + Feedback)**Break skills into fundamentals, practice consistently, and refine based on feedback for rapid improvement.</p>
<h4>Root Cause Analysis</h4>
<p><strong>Problem = Symptom — Root Cause</strong>Identify and address the root cause to eliminate recurring issues, rather than treating surface symptoms.</p>
<h4>Value Proposition in Marketing</h4>
<p><strong>Value = (Perceived Benefit — Perceived Cost) × Emotional Connection</strong>Maximize perceived benefit, minimize perceived cost, and strengthen emotional resonance to create a compelling offer.</p>
<p>The best leaders, creators, and problem-solvers don’t settle for easy answers or borrowed wisdom. They start with first principles, building solutions that are smarter, simpler, and more effective.</p>
<p>Whether you’re designing a product, managing a team, or tackling a tough problem, first principles thinking is a compass that points to clarity. It’s a way to cut through the noise, uncover what matters, and create something truly meaningful.</p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/the-grounds-of-first-principles/4a95162a4e6be119.png" alt=""></p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/the-grounds-of-first-principles">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Ideas</category><category>Entrepreneurship</category><category>Creativity</category><category>Life</category><category>Engineering</category>
    </item>
    <item>
      <title>Resolving React 19 Dependency Conflicts Without Downgrading</title>
      <link>https://zachshallbetter.com/writing/resolving-react-19-dependency-conflicts-without-downgrading</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/resolving-react-19-dependency-conflicts-without-downgrading</guid>
      <pubDate>Mon, 13 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>Tackling Peer Conflicts in Modern React Projects</description>
      <content:encoded><![CDATA[<p><strong>React 19</strong> has introduced features like <strong>Server Components</strong>, <strong>Turbopack</strong>, and <strong>Concurrent Rendering</strong>. While these innovations enhance performance, they’ve also led to various <strong>peer dependency conflicts</strong>across the ecosystem. If you can’t live without these features, this article is a blended guide to resolving the conflicts without resorting to using <code>--force, --legacy-peer-deps</code>, or downgrading to React 18.</p>
<p>I first experienced this issue with <a href="https://www.radix-ui.com/">Radix UI</a> and <a href="https://ui.shadcn.com/">ShadCN</a>, which <a href="https://ui.shadcn.com/docs/react-19.">they addressed</a>, but after some experimenting I found similar issues in libraries like <a href="https://www.npmjs.com/package/@testing-library/react">@testing-library/react</a>, <a href="https://www.npmjs.com/package/react-scripts">react-scripts</a>, <a href="https://www.npmjs.com/package/eslint-plugin-react">eslint-plugin-react</a>, <a href="https://react-redux.js.org/">react-redux</a>, <a href="https://recharts.org/">recharts</a>, <a href="https://react-cmdk.com">cmdk</a>, and at one point <a href="https://www.npmjs.com/package/react-dom">react-dom</a>. Assuming many of these will receive updates (like React Dom), so perform your own experiments.</p>
<p><strong>Note, before diving in:</strong> The quickest solve is to use****<a href="https://yarnpkg.com/">Yarn</a> or <a href="https://vite.dev/">Vite</a>, both of which are great. I’ll cover the other options below.</p>
<h3><strong>Understanding Peer Dependency Conflicts</strong></h3>
<p><strong>Peer dependencies</strong> dictate which versions of a package (e.g., React) are compatible with other libraries. Conflicts typically arise when:</p>
<ul>
<li><p><strong>Outdated Libraries</strong>: Libraries declare compatibility only up to React 18.</p>
</li>
<li><p><strong>Strict Version Constraints</strong>: Exact versions are required, disallowing React 19.</p>
</li>
<li><p><strong>Multiple React Versions</strong>: Different packages install conflicting versions of React.</p>
</li>
<li><p><strong>Stricter Package Manager Enforcement</strong>: npm 7+ enforces peer dependency rules more strictly.</p>
</li>
</ul>
<p>These conflicts create installation errors or runtime issues like:<code>Error: Invalid hook call. Hooks can only be called inside of the body of a function component.</code></p>
<h4>Example Scenarios</h4>
<p>A known issue with create-react-app (CRA) occurs when using React 19. The default installation installs React 19, while some dependencies, like @testing-library/react, specify a peer dependency of react@”¹⁸.0.0&quot;. This leads to errors like <code>npm ERR! peer react@&quot;^18.0.0&quot; from @testing-library/react@13.4.0.</code></p>
<p>Attempts to resolve this with — legacy-peer-deps or by specifying a script version like <code>npx create-react-app myprog — scripts-version react-scripts@5.0.1</code> . still result in conflicts.</p>
<p><strong>Side Note:</strong> If you’re cool with React 18 install it within your project before running create-react-app.</p>
<pre><code>npm install react@18 react-dom@18
npx create-react-app myprog
</code></pre>
<h3><strong>How to Identify Dependency Conflicts</strong></h3>
<p>Here’s how to pinpoint which packages are causing peer dependency conflicts:</p>
<h4>1. Run npm ls to View the Dependency Tree</h4>
<p>The <code>npm ls </code> command shows your project’s dependency tree, helping identify conflicting packages</p>
<p>This will display the versions of React used by different packages and highlight conflicts with UNMET PEER DEPENDENCY errors.</p>
<h4>2. Use npm install to Check for Conflicts</h4>
<p>Attempting to use <code>npm install</code> or running <code>npm update</code> will often reveal peer dependency conflicts:</p>
<p>If there are conflicts, npm will display warnings like:<code>npm WARN some-package@1.0.0 requires a peer of react@¹⁸ but none is installed.</code></p>
<h4>3. Inspect Conflicts Using npm outdated</h4>
<p>The <code>npm outdated</code> command shows outdated dependencies and helps you identify potential conflicts with newer versions. Focus on packages related to React, as they are likely the source of conflicts.</p>
<h4>4. Audit Dependencies with npm ls — depth=0</h4>
<p>Use <code>npm ls — depth=0</code> to list all top-level dependencies (those directly installed in your project). This will help you narrow down the packages to inspect further for peer dependency issues.</p>
<h4>5. Check Dependency Versions in package.json</h4>
<p>If the conflicting versions aren’t obvious, use <code>cat package.json</code>to inspect your package.json file. Then, compare the specified versions of React, React DOM, and other critical libraries with the required peer dependencies of conflicting packages.</p>
<h4>6. Use npm dedupe to Detect Duplicates</h4>
<p>Sometimes, conflicts occur due to duplicate React installations. Run the <code>npm dedupe</code> to deduplicate your node_modules. Then, re-run npm ls react to verify whether multiple React versions are installed.</p>
<h4>7. Use yarn why</h4>
<p>For Yarn users, <code>yarn why</code> provides detailed information about why a package is installed and which dependencies require it:</p>
<hr>
<h3><strong>Resolving Peer Dependency Conflicts</strong></h3>
<p>Once you’ve identified the conflicts, any of these strategies can</p>
<h4><strong>1. Manually rollback the version in your project</strong></h4>
<p>Manually install compatible versions of conflicting packages using <code>npm install @</code> , note this could cause issues with the package if it relies on features found in 19.</p>
<h4><strong>2. Use overrides (npm) or resolutions (yarn)</strong></h4>
<p>Force compatible versions without altering global settings forcing compatible versions without altering global settings in package.json and then run <code>npm install</code>.</p>
<pre><code>// NPM overrides
{
  &quot;overrides&quot;: {
    &quot;react&quot;: &quot;19.x&quot;,
    &quot;react-dom&quot;: &quot;19.x&quot;
  }
}

// Yarn resolutions
{
  &quot;resolutions&quot;: {
    &quot;react&quot;: &quot;19.x&quot;,
    &quot;react-dom&quot;: &quot;19.x&quot;
  }
}
</code></pre>
<h4>3. Request Updates from Maintainers</h4>
<p>Search the package’s repository for similar issues, write a ticket, and ask the maintainers for React 19 support. While waiting, apply other fixes temporarily.</p>
<h4><strong>4. Fork and Patch Outdated Libraries</strong></h4>
<p>If a critical library hasn’t updated its peerDependencies:</p>
<ul>
<li><p>**Fork the library on GitHub.**Start by forking the library’s repository to your own GitHub account. This ensures you have full control over the code and can modify it as needed without affecting the original project.</p>
</li>
<li><p><strong>Update the package to support React 19.</strong>• Open the package.json file in the forked repository.• Modify the peerDependencies section to include React 19.</p>
</li>
<li><p><strong>Test and Verify Compatibility</strong>• Run the library’s test suite and insure they resolve. The Readme or package.json scripts section should identify how that’s done.</p>
</li>
<li><p><strong>Publish Your Fork</strong>• Publish the updated package to your npm account under a scoped name, e.g.,<code>@your-username/</code></p>
</li>
<li><p><strong>Be a Good Code and Ecosystem Steward</strong>• Submit a <strong>well-documented pull request</strong> (PR) to the original repository.• Clearly explain the changes with “why”, “how” and “what”• Follow their contribution guidelines (generally in <code>/CONTRIBUTORS.md</code> )</p>
</li>
</ul>
<h4><strong>5. Switch to Compatible Alternatives</strong></h4>
<p>If an outdated package shows no sign of updating, replace it with a modern, actively maintained alternative. For example, in my case, I would use libraries like <a href="https://mui.com/">MUI</a> or <a href="https://www.chakra-ui.com/">Chakra UI</a>****instead of <strong>ShadCN.</strong></p>
<h4><strong>6. Isolate Packages in a Monorepo</strong></h4>
<p>Use tools like <a href="https://nx.dev/">Nx</a> or <a href="https://turbo.build/">Turborepo</a> to structure your project in a monorepo, isolating conflicting packages in separate workspaces to minimize conflicts.</p>
<h4><strong>7. Custom Dependency Resolution Script</strong></h4>
<p>If you need to automate the process for installation, deployment, or modifying node_modules post-installation to resolve peer dependency conflicts:</p>
<ul>
<li><p>Install conflicting packages.</p>
</li>
<li><p>Write a script to update peerDependencies in their package.json files.</p>
</li>
<li><p>Rebuild the project.</p>
</li>
</ul>
<p>The script might look something like this:</p>
<pre><code>// This script modifies the peerDependencies of conflicting packages directly within node_modules.
// Use Node.js to automate this process by adding &quot;node resolve-peer-deps.js&quot; to your package.json config

const fs = require(&amp;#x27;fs&amp;#x27;);
const path = require(&amp;#x27;path&amp;#x27;);

const packagesToUpdate = [
  {
    name: &amp;#x27;@testing-library/react&amp;#x27;,
    newPeerDependencies: {
      react: &amp;#x27;&gt;=18.0.0 &lt;20.0.0&amp;#x27;,
      &amp;#x27;react-dom&amp;#x27;: &amp;#x27;&gt;=18.0.0 &lt;20.0.0&amp;#x27;,
    },
  },
  {
    name: &amp;#x27;another-library&amp;#x27;,
    newPeerDependencies: {
      react: &amp;#x27;&gt;=18.0.0 &lt;20.0.0&amp;#x27;,
    },
  },
];

const resolvePath = (pkgName) =&gt; path.resolve(&amp;#x27;node_modules&amp;#x27;, pkgName, &amp;#x27;package.json&amp;#x27;);

const readJson = (filePath) =&gt; JSON.parse(fs.readFileSync(filePath, &amp;#x27;utf8&amp;#x27;));

const writeJson = (filePath, data) =&gt; fs.writeFileSync(filePath, JSON.stringify(data, null, 2));

const updatePeerDeps = ({ name, newPeerDependencies }) =&gt; {
  try {
    const packageJsonPath = resolvePath(name);
    if (!fs.existsSync(packageJsonPath)) throw new Error(`Package not found: ${name}`);

    const packageJson = readJson(packageJsonPath);
    packageJson.peerDependencies = { ...packageJson.peerDependencies, ...newPeerDependencies };
    writeJson(packageJsonPath, packageJson);

    console.log(`[Updated] ${name} peerDependencies`);
  } catch (error) {
    console.error(`[Error] ${name}: ${error.message}`);
  }
};

packagesToUpdate.forEach(updatePeerDeps);
</code></pre>
<h4>8. Monitor Updates with Renovate or Dependabot</h4>
<p>Automate dependency updates with tools like <a href="https://www.whitesourcesoftware.com/free-developer-tools/renovate/">Renovate</a>, <a href="https://github.com/dependabot">Dependabot</a>, or my go-to <a href="https://www.npmjs.com/package/npm-check-updates">npm-check-updates (ncu)</a>.</p>
<h4>9. Just use — legacy-peer-deps and hang tight</h4>
<p>Let’s face it: dealing with peer dependency conflicts is never fun but this isn’t a show stopper.</p>
<p>The key is experimentation. Not every project will need the same fix, try out a few of these approaches, see what sticks, and maybe even discover a trick or two along the way, save it in your <a href="https://gist.github.com/zachshallbetter">gist</a> or <a href="https://code.visualstudio.com/docs/editor/userdefinedsnippets">snippits</a>, and call it a day.</p>
<p>Good luck!</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/resolving-react-19-dependency-conflicts-without-downgrading">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Software development</category><category>Productivity</category><category>Technology</category><category>Programming</category><category>React</category>
    </item>
    <item>
      <title>Market Forecasting for Product People</title>
      <link>https://zachshallbetter.com/writing/market-forecasting-for-product-people</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/market-forecasting-for-product-people</guid>
      <pubDate>Mon, 13 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>Turning Insights Into Strategy</description>
      <content:encoded><![CDATA[<p>Market forecasting is often viewed as a specialty for data scientists or financial analysts, but it’s an essential skill for product managers. It provides the foundation for informed decision-making, helping product teams navigate uncertainties, seize opportunities, and align with business goals. Forecasting isn’t just about crunching numbers — it’s about transforming data into actionable insights.</p>
<p>This article explores how product professionals can leverage market forecasting to inform strategies, prioritize features, and stay ahead of competitors.</p>
<h3><strong>Understand the Basics of Market Forecasting</strong></h3>
<h4><strong>What Is Market Forecasting?</strong></h4>
<p>Market forecasting predicts future demand, trends, and opportunities within a specific market or industry. It analyzes historical data, customer behavior, competitive landscapes, and macroeconomic trends to guide product decisions.</p>
<h4><strong>Why It Matters for Product People</strong>:</h4>
<ul>
<li><p><strong>Identify Market Opportunities</strong>: Spot unmet needs or emerging trends before competitors.</p>
</li>
<li><p><strong>Optimize Resource Allocation</strong>: Invest in features or products aligned with growth opportunities.</p>
</li>
<li><p><strong>Reduce Risk</strong>: Anticipate shifts in demand or disruptions that could impact the roadmap.</p>
</li>
<li><p><strong>Enhance Stakeholder Buy-In</strong>: Use data-driven insights to justify decisions to executives and investors.</p>
</li>
</ul>
<h3><strong>Key Forecasting Techniques for Product Managers</strong></h3>
<h4><strong>1. Trend Analysis</strong></h4>
<ul>
<li><p><strong>What It Is</strong>: Examines historical patterns to predict future behavior.</p>
</li>
<li><p><strong>Use Case</strong>: Forecast demand for an existing product by analyzing sales data.</p>
</li>
<li><p><strong>Tools</strong>: Google Trends, Tableau, Excel.</p>
</li>
</ul>
<h4><strong>2. Customer Segmentation</strong></h4>
<ul>
<li><p><strong>What It Is</strong>: Divides the market into distinct groups based on behavior, demographics, or preferences.</p>
</li>
<li><p><strong>Use Case</strong>: Predict which customer segments are likely to adopt a new feature.</p>
</li>
<li><p><strong>Tools</strong>: CRM systems, customer surveys, behavioral analytics platforms.</p>
</li>
</ul>
<h4><strong>3. Market Sizing</strong></h4>
<ul>
<li><p><strong>What It Is</strong>: Estimates the total revenue opportunity for a product or feature.</p>
</li>
<li><p><strong>Use Case</strong>: Assess whether a new market segment is worth pursuing.</p>
</li>
<li><p><strong>Tools</strong>: TAM/SAM/SOM frameworks, industry reports.</p>
</li>
</ul>
<h4><strong>4. Predictive Analytics</strong></h4>
<ul>
<li><p><strong>What It Is</strong>: Uses machine learning and statistical models to forecast outcomes.</p>
</li>
<li><p><strong>Use Case</strong>: Predict churn rates or the impact of a pricing change.</p>
</li>
<li><p><strong>Tools</strong>: Python, R, Power BI.</p>
</li>
</ul>
<h4><strong>5. Scenario Planning</strong></h4>
<ul>
<li><p><strong>What It Is</strong>: Explores multiple potential future outcomes based on key variables.</p>
</li>
<li><p><strong>Use Case</strong>: Plan for various launch scenarios, from conservative to aggressive adoption rates.</p>
</li>
<li><p><strong>Tools</strong>: Decision trees, Monte Carlo simulations.</p>
</li>
</ul>
<h3><strong>Steps to Build a Product-Focused Forecast</strong></h3>
<h4><strong>Step 1: Define Your Objective</strong></h4>
<p>Clearly outline what you aim to achieve, such as feature prioritization, market entry, or revenue projection.</p>
<ul>
<li><strong>Example</strong>: “Forecast adoption rates for a new subscription feature in the U.S. market.”</li>
</ul>
<h4><strong>Step 2: Gather Relevant Data</strong></h4>
<p>Collect both internal and external data to inform your forecast.</p>
<ul>
<li><p><strong>Internal Data</strong>: Historical sales, customer feedback, usage metrics.</p>
</li>
<li><p><strong>External Data</strong>: Competitor trends, economic indicators, industry reports.</p>
</li>
<li><p><strong>Example</strong>: Use App Annie or Sensor Tower for mobile app benchmarking.</p>
</li>
</ul>
<h4><strong>Step 3: Choose a Forecasting Model</strong></h4>
<p>Select a model that fits the complexity of your data and objective.</p>
<ul>
<li><p><strong>Linear Regression</strong>: For straightforward trends.</p>
</li>
<li><p><strong>Time-Series Analysis</strong>: For seasonal data.</p>
</li>
<li><p><strong>Predictive Models</strong>: For complex, multi-variable forecasts.</p>
</li>
</ul>
<h4><strong>Step 4: Validate Assumptions</strong></h4>
<p>Ensure your assumptions are realistic and data-driven.</p>
<ul>
<li><strong>Example</strong>: If predicting 20% growth, confirm this aligns with historical data or market benchmarks.</li>
</ul>
<h4><strong>Step 5: Monitor and Iterate</strong></h4>
<p>Continuously compare forecasts with actual performance, refining models as necessary.</p>
<ul>
<li><strong>Example</strong>: Use a rolling forecast updated quarterly.</li>
</ul>
<h3><strong>Using Forecasting to Inform Product Strategy</strong></h3>
<h4><strong>Prioritizing Features</strong></h4>
<p>Estimate revenue or engagement impacts for specific features.</p>
<ul>
<li><strong>Example</strong>: Predict how integrating a payment gateway will increase app transactions.</li>
</ul>
<h4><strong>Market Entry</strong></h4>
<p>Assess potential size and growth of new markets.</p>
<ul>
<li><strong>Example</strong>: Use market sizing to decide between launching in APAC or EMEA.</li>
</ul>
<h4><strong>Pricing Strategies</strong></h4>
<p>Forecast price elasticity to predict how changes will affect demand.</p>
<ul>
<li><strong>Example</strong>: Model the impact of a subscription price increase using historical data.</li>
</ul>
<h4><strong>Resource Allocation</strong></h4>
<p>Forecast ROI to identify high-impact initiatives.</p>
<ul>
<li><strong>Example</strong>: Allocate R&amp;D resources to products with the highest growth potential.</li>
</ul>
<h3><strong>Metrics That Matter</strong></h3>
<ul>
<li><p><strong>Total Addressable Market (TAM)</strong>: Helps assess the overall revenue potential of a market, guiding high-level strategic decisions.</p>
</li>
<li><p><strong>Customer Acquisition Cost (CAC)</strong>: Measures the efficiency of marketing and sales efforts, aiding resource prioritization.</p>
</li>
<li><p><strong>Monthly Recurring Revenue (MRR)</strong>: Tracks subscription growth, informing decisions on SaaS features and pricing strategies.</p>
</li>
<li><p><strong>Churn Rate</strong>: Evaluates customer retention, identifying areas for product improvement.</p>
</li>
<li><p><strong>Feature Adoption Rate</strong>: Measures the success of new features, assessing their impact on user engagement and ROI.</p>
</li>
</ul>
<h3><strong>Common Pitfalls to Avoid</strong></h3>
<h4><strong>Over-Reliance on Historical Data</strong></h4>
<ul>
<li><p><strong>Problem</strong>: Markets change, and past trends may not predict future behavior.</p>
</li>
<li><p><strong>Solution</strong>: Combine historical data with real-time insights.</p>
</li>
</ul>
<h4><strong>Ignoring Qualitative Insights</strong></h4>
<ul>
<li><p><strong>Problem</strong>: Numbers alone don’t reveal user motivations.</p>
</li>
<li><p><strong>Solution</strong>: Pair analytics with user interviews and surveys.</p>
</li>
</ul>
<h4><strong>Underestimating Market Complexity</strong></h4>
<ul>
<li><p><strong>Problem</strong>: Single-variable models miss nuances.</p>
</li>
<li><p><strong>Solution</strong>: Use multi-variable forecasting and scenario planning.</p>
</li>
</ul>
<h4><strong>Failing to Act on Insights</strong></h4>
<ul>
<li><p><strong>Problem</strong>: Forecasts are wasted if not translated into action.</p>
</li>
<li><p><strong>Solution</strong>: Build action plans tied directly to forecast outcomes.</p>
</li>
</ul>
<h3><strong>Useful Product Tools to Leverage</strong></h3>
<h4><strong>Basic Tools for Product Teams</strong>:</h4>
<ul>
<li><p><a href="https://www.airtable.com/">Airtable</a>**:**Combines spreadsheet functionality with a database interface. Ideal for managing workflows, conducting trend analyses, and calculating TAM (Total Addressable Market).</p>
</li>
<li><p><a href="https://analytics.google.com/analytics/web/">Google Analytics 4 (GA4)</a>**:**Tracks web traffic, user behavior, and conversion rates. With AI-driven insights, it’s perfect for understanding customer interactions.</p>
</li>
<li><p><a href="https://www.hotjar.com/">Hotjar</a>**:**A tool for heat maps, session recordings, and surveys that provides qualitative data on user behavior and sentiment.</p>
</li>
<li><p><a href="https://www.typeform.com/">Typeform</a>**:**Allows the creation of conversational, user-friendly surveys to collect customer feedback, integrate with CRM tools, and analyze data efficiently.</p>
</li>
<li><p><a href="https://miro.com/">Miro</a>**:**A virtual whiteboard for brainstorming, mind mapping, and visualizing workflows, fostering team collaboration in product planning.</p>
</li>
<li><p><a href="https://trello.com/">Trello</a>**:**Simple project management with kanban boards, ideal for managing product tasks and tracking feature development timelines.</p>
</li>
<li><p><a href="https://mixpanel.com/">Mixpanel</a>**:**A product analytics tool that tracks user interactions, enabling teams to understand how users engage with features over time.</p>
</li>
<li><p><a href="https://www.optimizely.com/">Optimizely</a>**:**Enables multivariate testing and feature experimentation, optimizing product performance and user experience.</p>
</li>
</ul>
<h4><strong>Advanced Tools</strong>:</h4>
<ul>
<li><p><a href="https://lookerstudio.google.com/">Looker Studio (formerly Google Data Studio)</a>**:**Creates interactive dashboards and detailed data visualizations, integrating with diverse data sources for real-time analysis.</p>
</li>
<li><p><a href="https://www.snowflake.com/">Snowflake</a>**:**A cloud-based data warehouse that enables scalable data storage and analysis, essential for large-scale market forecasting.</p>
</li>
<li><p><a href="https://www.python.org/">Python</a> and <a href="https://www.r-project.org/">R</a>**:**Essential programming languages for predictive modeling, machine learning, and statistical analysis of market trends.</p>
</li>
<li><p><a href="https://www.statista.com/">Statista</a>**:**Offers a vast repository of market research, statistical data, and trend reports across industries.</p>
</li>
<li><p><a href="https://sensortower.com/">Sensor Tower</a><strong>: P</strong>rovides in-depth mobile app market intelligence, tracking competitor performance, user acquisition, and revenue benchmarks.</p>
</li>
<li><p><a href="https://amplitude.com/">Amplitude</a>**:**Tracks user behavior and product engagement, providing actionable insights to optimize user retention and drive growth.</p>
</li>
<li><p><a href="https://www.tableau.com/">Tableau</a>**:**A leading data visualization tool for analyzing large datasets, creating clear, compelling charts and dashboards.</p>
</li>
<li><p><a href="https://powerbi.microsoft.com/">Power BI</a>**:**A Microsoft tool for advanced analytics, enabling detailed reports, predictive insights, and interactive visualizations.</p>
</li>
<li><p><a href="https://heap.io/">Heap</a>**:**Automatically captures every user interaction, allowing teams to analyze product usage without manual event tagging.</p>
</li>
<li><p><a href="https://www.gartner.com/en/digital-markets">Gartner Digital Markets</a><strong>:</strong> Provides industry-specific reports, competitive analysis, and actionable insights into tech and software markets.</p>
</li>
<li><p><a href="https://www.domo.com/">Domo</a>**:**Integrates data from multiple sources, delivering real-time business intelligence for informed product decisions.</p>
</li>
<li><p><a href="https://www.data.ai/en/solutions/app-annie-intelligence/">App Annie Intelligence</a>**:**Offers detailed mobile market analysis, including download trends, user demographics, and revenue insights.</p>
</li>
</ul>
<h4><strong>Emerging Tools and Platforms</strong></h4>
<ul>
<li><p><a href="https://www.databricks.com/">Databricks</a>**:**A unified analytics platform combining data engineering, machine learning, and business intelligence for end-to-end forecasting.</p>
</li>
<li><p><a href="https://www.growthbook.io/">GrowthBook</a>**:**An experimentation platform for A/B testing product features, helping teams validate forecasts and measure impact.</p>
</li>
<li><p><a href="https://www.brandwatch.com/crimson-hexagon/">Crimson Hexagon</a>**:**A social media analysis tool that monitors market sentiment and emerging trends to refine product strategies.</p>
</li>
<li><p><a href="https://knoema.com/">Knoema</a>**:**Provides access to global economic, demographic, and industry data for high-level market trend analysis.</p>
</li>
<li><p><a href="https://segment.com/">Segment</a>**:**A customer data platform that unifies data across tools, helping teams create a complete view of user behavior.</p>
</li>
</ul>
<h3><strong>The Strategic Mindset</strong></h3>
<p>Market forecasting isn’t just about crunching numbers — it’s about asking the right questions:</p>
<ul>
<li><p><strong>What do these trends mean for my roadmap?</strong></p>
</li>
<li><p><strong>How can forecasts align with business goals?</strong></p>
</li>
<li><p><strong>What risks and opportunities do these insights reveal?</strong></p>
</li>
</ul>
<p>By approaching forecasting as a strategic tool, product leaders can make better decisions, build impactful products, and guide their teams with confidence.</p>
<h3><strong>Forecasting as a Strategic Compass</strong></h3>
<p>In a fast-moving, unpredictable market, forecasting equips product leaders with a compass to navigate uncertainty. By mastering the art and science of forecasting, you’re not just predicting the future — you’re shaping it. Use these tools and techniques to turn data into actionable insights, guiding your team to build products that meet today’s needs and anticipate tomorrow’s demands.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/market-forecasting-for-product-people">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Data</category><category>Marketing</category><category>Analytics</category><category>Product management</category><category>Business</category>
    </item>
    <item>
      <title>The Cruelty of Hiring</title>
      <link>https://zachshallbetter.com/writing/the-cruelty-of-hiring</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/the-cruelty-of-hiring</guid>
      <pubDate>Sun, 12 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>How Flawed Hiring Systems Undermine Teams and Devalue Talent</description>
      <content:encoded><![CDATA[<p>Alysia’s excitement was electric as she prepared for the opportunity she had dreamed of for years. This wasn’t just any job — it was a role at a company whose mission resonated deeply with her values, the kind of place where she envisioned thriving both professionally and personally. She meticulously tailored her creative résumé, curated a portfolio that vividly told her story, and rehearsed thoughtful answers for every question she could anticipate. In her mind, she could already see herself stepping into the office, her passion recognized, her hard work validated. <em>This could be my forever job,</em> she told herself, her optimism driving her forward.</p>
<p>Yet, after submitting her work, days stretched into weeks without any acknowledgment. Her excitement began to waver, weighed down by the oppressive silence and growing uncertainty. The spark of hope that had fueled her meticulous preparation dimmed with each passing day. Just as she started to accept that her application might have vanished into the void, an email arrived: an invitation to interview. Her excitement reignited, her determination surging anew.</p>
<p>But that excitement was tempered by a familiar, gnawing anxiety. The prolonged silence had left her questioning whether her application had been taken seriously or if she had simply gotten lucky. She tried to reassure herself, thinking, <em>Maybe the team is overwhelmed with competing priorities, or they’re finalizing internal decisions.</em> She clung to the belief that the delay was merely logistical, not a reflection of her worth as a candidate.</p>
<p>Alysia doubled down on her preparation. She practiced her responses, refined her portfolio, and threw herself into research, convinced that this could be the pivotal moment of her career. She prioritized this opportunity above others, pouring all her energy into ensuring she left no stone unturned. But deep down, she feared spreading herself too thin, worried that her hyper-focus on this one role might hinder her ability to pursue other prospects. Still, she gave everything — emotionally, intellectually, and wholeheartedly — because she believed this role was worth it.</p>
<p>The first interview went well enough, leaving her cautiously optimistic. <em>This could still work out,</em> she told herself, grasping onto the interviewer’s encouraging tone and subtle affirmations. But then, once again, came the waiting. Days passed without follow-up, followed by weeks of silence. Alysia found herself obsessively checking her inbox, her excitement fading with every unopened email. <em>Should I reach out?</em> she wondered. <em>Would that seem pushy?</em> She hesitated across several days, fearful of appearing impatient, but finally resolved to send a polite follow-up. Her carefully worded email, written with both professionalism and vulnerability, went unanswered, leaving her feeling exposed and uncertain.</p>
<p>The need to “check in” felt humiliating — a stark reminder of the power imbalance inherent in the hiring process. She had already invested significant time and effort presenting herself as the ideal candidate, yet she found herself questioning, <em>Why should I have to infantilize myself?</em> Shouldn’t the company, in turn, show the courtesy of keeping her informed? Worse still, a nagging fear crept in: <em>Did I hurt my chances by following up?</em> she wondered, second-guessing even her smallest acts of self-advocacy.</p>
<p>When a second interview was finally scheduled nearly a month later, Alysia felt relief, but it was tinged with frustration. <em>Is this really how the process works? Do they have any idea how stressful this is?</em> she thought. Despite her growing doubts, she resolved to stay focused. Once again, she prepared meticulously, determined to maintain her professionalism and optimism.</p>
<p>When the third interview came — in what seemed like a rushed, last-minute request — it felt like a final straw. The meeting was hastily scheduled at an awkward time, with little regard for her availability. This time, the interviewer seemed overzealous, as if compensating for prior lapses in the process. The questions became hyper-focused on niche issues related to the previous employee’s shortcomings, as though the goal was to uncover how Alysia might similarly fail. The conversation shifted from evaluating her strengths to probing for risks, leaving her feeling interrogated rather than assessed.</p>
<p>Afterward, she was told, once again, to wait for the next steps. Days turned into weeks, and her financial worries began to mount. Her savings dwindled, and the pressure to find a stable role grew unbearable. She had been applying to other jobs out of necessity, though her confidence was shaken by the lack of progress here. She felt caught in limbo, unable to fully commit to other opportunities while holding on to the faint hope that this role might still come through.</p>
<p>Finally, after weeks of silence, she received an email. Her heart raced as she opened it, hoping for good news. Instead, it was a generic rejection, as impersonal and cold as the initial application confirmation email. No acknowledgment of the effort she had poured into the process, no feedback, no closure — just an automated response.</p>
<p>The email felt like a slap in the face, reducing her and her effort to a meaningless template in letter form. Her faith in the process was shattered. All that remained was the bitter realization that her time and energy had been discarded without a second thought, and she would need to continue despite the knot that had been tied in her stomach.</p>
<h3>Behind the Curtain</h3>
<p>Nearly a month before Alysia submitted her application, the team she aspired to join faced a sudden shake-up. A key member had tendered their resignation, giving a polite but succinct two-week notice. While not entirely unexpected, the timing was disruptive. The team, already stretched thin, now found themselves grappling with unfinished projects, knowledge gaps, and mounting deadlines. With clients growing restless and workloads intensifying, the resignation pushed an already fragile system to its breaking point.</p>
<p>The hiring manager felt the pressure immediately. There was no time to reflect on the underlying issues that had led to the departure or to re-evaluate the team’s dynamics. The priority was survival: find a replacement quickly to stabilize operations. Human Resources stepped in with a clear directive — define the role, launch the hiring process, and avoid delays or costly mistakes.</p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/the-cruelty-of-hiring/e502c4952fddb207.png" alt="An illustration of a man at a table working late into the evening. By Zach Shallbetter"></p>
<p>However, urgency often amplifies existing cracks in the system. “Every day the role remained unfilled, the team’s productivity slipped further,” one manager later explained. Studies have shown that even brief vacancies can erode morale and increase stress, and this team was no exception. “It felt like we were sprinting to catch up, only to realize the finish line kept moving,” a team member candidly noted.</p>
<p>The job description was hastily revised, relying heavily on outdated language from years prior. In an effort to hedge against further disruption, additional “nice-to-have” skills were elevated to mandatory requirements. The result was a role that sought not only to replace the outgoing employee but also to find someone capable of withstanding the very pressures that had driven their predecessor away.</p>
<p>For the team, the disconnect between leadership’s urgency and the realities of their work became increasingly apparent. The Applicant Tracking System (ATS), introduced months earlier, was intended to streamline the hiring process by filtering résumés and surfacing top prospects. On paper, it seemed like an efficient solution, but in practice, the ATS couldn’t adapt to the nuances of the team’s needs. “The system was great for speeding up initial screenings,” one team member admitted, “but it missed the mark when it came to recognizing the kind of adaptability and problem-solving we really needed.”</p>
<p>Leadership’s directive to “move fast but get it right” left the team grappling with conflicting priorities. While the ATS efficiently flagged candidates based on keywords, it failed to account for intangible qualities like cultural fit, flexibility, or the ability to navigate high-pressure situations — qualities that would have made a candidate truly valuable to the team. This mismatch led to frustration, as promising candidates were overlooked, and others advanced based on surface-level criteria.</p>
<p>The team’s growing frustration stemmed not only from the system’s limitations but also from the constant changes in priorities. “We needed someone who could hit the ground running, but every time the role’s requirements shifted, it felt like we were back at square one,” a team lead reflected. The process, which was meant to stabilize operations, instead became a cycle of unmet expectations and lost time.</p>
<p>The team’s urgency, combined with leadership’s fear of making a poor hire, resulted in a reactive, piecemeal approach. HR worked tirelessly to bridge the gaps, but the lack of clarity about the role’s true needs and strained communication between leadership and the hiring team led to delays and missteps. What should have been a collaborative process felt more like crisis management, leaving HR scrambling to reconcile conflicting demands while candidates like Alysia waited in silence.</p>
<h3><strong>Rational Intent</strong></h3>
<p>From HR’s perspective, the hiring process was carefully structured to balance efficiency and fairness. The recent adoption of systems like the Applicant Tracking System aimed to address common inefficiencies, allowing HR to quickly identify top candidates and streamline early evaluations. “The ATS was supposed to be our silver bullet — a way to reduce time-to-hire while maintaining accuracy,” one HR lead explained.</p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/the-cruelty-of-hiring/93c62605d71f8328.png" alt=""></p>
<p>Initially, the system performed as expected, saving hours of manual résumé screening. Leadership took comfort in its data-driven outputs, confident the technology would deliver consistent, high-quality results. But as the team’s needs evolved and client deadlines loomed, cracks began to show.</p>
<p>“It wasn’t long before we realized the system wasn’t perfect,” a hiring team member admitted during a post-hiring review. “It’s great at picking up keywords, but it can’t measure things like adaptability or creative problem-solving.” Internal reviews revealed that nearly 70% of qualified candidates were being filtered out due to rigid keyword matches, leaving unconventional but promising applicants overlooked. This highlighted a critical gap: while the system streamlined initial screenings, it often excluded the very traits that could drive team innovation and resilience.</p>
<p>To compensate, HR began manually adjusting ATS outputs to align with the team’s shifting priorities. “We were trying to steer a moving ship,” one recruiter reflected. “By the time we adjusted filters, the priorities had already changed, and existing candidates were nullified” These constant revisions added complexity, slowed progress, and deepened the disconnect between leadership’s expectations and the realities of the process.</p>
<p>he interview stage reflected these same challenges. HR, already stretched thin, scrambled to coordinate schedules and provide interviewers with updated role details, but misalignment persisted. “Every conversation felt like starting over,” one candidate recalled. “It was obvious the interviewers weren’t on the same page.” For the overworked team, rushed preparation meant interviews often defaulted to surface-level questions, lacking the depth needed to assess skills or fit meaningfully. The result was a frustrating and disjointed experience for both candidates and interviewers.</p>
<p>Leadership’s growing fear of making a poor hire further complicated matters. “No one wanted to make the wrong call, so decisions were delayed until we had absolute certainty,” a department head explained. While this caution was understandable, it transformed interviews into risk assessments rather than opportunities to connect with candidates. Feedback loops slowed and became overly guarded, compounding the sense of paralysis within the process.</p>
<p>What began as a rational, efficiency-driven system devolved into a labyrinth of adjustments, delays, and second-guessing. HR and leadership found themselves trapped in a cycle where the relentless pursuit of precision eroded the candidate experience and strained team cohesion.</p>
<h3>Calculated Caution</h3>
<p>Leadership’s cautious approach to hiring began with sound intentions: to avoid repeating the mistakes of the past and to ensure the right candidate was chosen. The stakes were undeniably high — hiring the wrong person could cost the company time, money, and potentially harm client relationships. “A bad hire doesn’t just affect the bottom line; it impacts team dynamics and trust,” one senior leader remarked. However, this caution quickly spiraled into a pattern of overcorrection. The Applicant Tracking System (ATS), initially hailed as a solution for inefficiencies, became a bottleneck as leadership’s priorities shifted and the fear of making a wrong hire grew.</p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/the-cruelty-of-hiring/43171dedb1b992a8.png" alt="An illustration of a team making decisions, by Zach Shallbetter"></p>
<p>The leadership team’s cautious approach to hiring began with sound intentions: to avoid repeating past mistakes and ensure the right candidate was chosen. The stakes were undeniably high — hiring the wrong person could cost the company time, money, and potentially harm client relationships. “A bad hire doesn’t just affect the bottom line; it impacts team dynamics and trust,” one senior leader remarked. However, this caution quickly spiraled into a pattern of overcorrection. The automated screening system, initially praised as a solution to inefficiencies, became a bottleneck as leadership’s priorities shifted and fear of making the wrong hire grew.</p>
<p>As one HR manager later observed, “Every adjustment to the filters felt like an attempt to fix a symptom without addressing the root cause — our lack of alignment.” Filters, originally tailored to the role’s requirements, were frequently modified to address evolving concerns, deepening the disconnect. Promising candidates were disqualified over minor omissions, while others advanced based on hastily added qualifications.</p>
<p>The financial and operational impact of these delays became increasingly apparent. During a departmental briefing, HR estimated that each day the role remained vacant cost the company approximately $1,500 in lost productivity. Deadlines slipped, client satisfaction wavered, and team frustration mounted. “We were already at capacity,” one team member explained. “Every day without a replacement felt like a month.”</p>
<p>Leadership’s fear of making a poor hire also influenced the interview process. Additional rounds were scheduled, often at the last minute, with little time for interviewers to prepare. Without clear guidance, interviews became repetitive, with redundant questions and overly specific inquiries. One candidate described the experience as “a carousel of confusion — each round felt like starting from scratch.”</p>
<p>Leadership’s involvement, intended to safeguard the process, ultimately prolonged it. Decisions were postponed under the guise of thoroughness, only to be rushed when deadlines loomed. This “hurry up and wait” cycle left everyone — HR, leadership, and candidates — feeling drained and disillusioned.</p>
<p>By the end of the process, Alysia’s enthusiasm had faded. What should have been an opportunity to showcase her skills instead felt like a series of tests designed to expose her weaknesses. Meanwhile, the organization missed more than just her talent; they lost time, morale, and credibility.</p>
<p>What began as a rational effort to mitigate risk devolved into a fragmented and overly cautious system, leaving both candidates and teams questioning its purpose.</p>
<h3><strong>The Ripple Effect</strong></h3>
<p>The hiring process, meant to identify and onboard top talent, had instead turned into a gauntlet that tested endurance more than aptitude. For Alysia, the experience was deeply personal, leaving her drained, demoralized, and questioning her value. But the dysfunction didn’t end with her; its impact rippled through the organization, harming more than just one candidate.</p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/the-cruelty-of-hiring/e3346c27007d1739.png" alt="An illustration of three people asking an idividual questions. by Zach Shallbetter"></p>
<p>The hiring process, designed to identify and onboard top talent, had instead become a gauntlet that tested endurance more than aptitude. For Alysia, the experience was deeply personal, leaving her drained, demoralized, and questioning her worth. But the dysfunction didn’t stop with her; its ripple effects permeated the organization, harming more than just one candidate.</p>
<p>What started as a well-intentioned effort to avoid hiring mistakes spiraled into a process riddled with inefficiencies and delays. “Every day we waited for updates felt like a countdown we couldn’t afford,” one team member recalled. These delays resulted in tangible losses: projects slowed, clients grew restless, and the remaining team members bore the weight of the unfilled role. During an internal review, HR estimated that the vacancy had cost the company thousands in lost productivity, compounding frustration and steadily eroding morale.</p>
<p>For candidates like Alysia, the waiting was excruciating. “The silence felt worse than the rejection,” she later shared. And she wasn’t alone — HR discussions revealed that nearly 75% of candidates have felt ghosted during the hiring process. These negative experiences leave lasting impressions; internal feedback indicated that 69% of candidates would refuse to reapply to companies with poor communication.</p>
<p>The overburdened team felt the strain with every delay. Deadlines slipped, workloads grew, and the tension between leadership’s caution and operational demands became increasingly palpable. “We were stuck in limbo,” admitted one contractor. “We couldn’t move forward, and we couldn’t catch a break.”</p>
<p>Even after the role was finally filled, the organization struggled to repair the damage. Team retrospectives revealed a decline in confidence in leadership, while HR noted a growing reluctance among potential future hires to engage with the company. One internal analysis found that poor hiring practices could increase turnover rates by as much as 20%, further destabilizing an already fragile system.</p>
<p>For Alysia, the rejection was more than a missed opportunity — it shattered her trust in the hiring process and left her questioning whether her passion and effort had been worth it. For the organization, the inability to balance efficiency with empathy cost more than time — it eroded trust, morale, and long-term credibility.</p>
<p>In the end, the ripple effects of a broken hiring process touched everyone involved, underscoring a crucial truth: when people are treated as data points rather than individuals, the cost is far greater than a missed hire.</p>
<p>Yet, while the damage was significant, it is not irreparable. The lessons from these missteps offer a clear roadmap for building a stronger, more compassionate hiring process — one that prioritizes people over process and fosters lasting trust and connection.</p>
<h3><strong>A Path Forward</strong></h3>
<p>To break the cycle of inefficiency and disillusionment, organizations must rethink their approach to hiring from the ground up. This begins with leadership. Leaders must shift from reactive, fear-driven decision-making to a framework grounded in trust, clarity, and collaboration. “The key is defining roles collaboratively with our teams,” one senior manager explained. “We need alignment from the start — otherwise, the process unravels.” Once roles are clearly defined, leadership must trust the systems and people in place to execute, intervening only when absolutely necessary and with transparency.</p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/the-cruelty-of-hiring/8de20941555322a4.png" alt=""></p>
<p>Small acts of empathy from leadership can make a lasting impact. One HR manager shared a story of a hiring lead who personally called a candidate to provide constructive feedback after an unsuccessful interview. “The candidate thanked us and said they’d never received such thoughtful input before,” the HR manager recalled. “Even though they didn’t get the role, they left the process feeling respected.” These gestures not only humanize the experience but also bolster the organization’s reputation as a caring and professional employer.</p>
<p>Organizations must also reassess their reliance on Applicant Tracking Systems. While these platforms efficiently manage high volumes of applications, their limitations have sparked internal debate. “Resumes are just the beginning,” an HR lead remarked during a recent review. “What we’re really looking for are qualities like creativity and adaptability — traits that don’t always show up in keywords.” Internal analyses showed that relying too heavily on ATS filters risked excluding nearly 70% of strong candidates, particularly those with unconventional career paths. To address this, leadership recognized the importance of creating alternative pathways to ensure that potential innovators weren’t overlooked.</p>
<p>Equally critical is re-centering the human element of hiring. “Candidates put so much into the process — it’s only fair we respect their efforts with clear communication,” a recruitment consultant noted during a team debrief. They emphasized that improving communication could significantly reduce candidate dropouts, a persistent issue. Structured yet empathetic interviews not only facilitate better evaluations but also foster genuine connections, ensuring candidates leave the process feeling valued — even if they’re not the right fit.</p>
<p>When these elements align — clear leadership, thoughtful use of technology, and a focus on empathy — the results can be transformative. During an internal strategy session, leadership reflected on companies that reported a 70% improvement in hire quality and a 25% boost in retention after prioritizing candidate experience. “Hiring isn’t just about filling a role,” an executive summarized. “It’s about building relationships and reinforcing the values that define us as an organization.”</p>
<p>Had these practices been in place, Alysia’s journey could have unfolded differently. Instead of feeling abandoned and uncertain, she might have received timely updates and constructive feedback, leaving her with a sense of respect and closure. Her passion could have been nurtured, and her potential retained, even if the role wasn’t the right fit. For the organization, such changes wouldn’t merely improve one candidate’s experience — they would signify a broader commitment to trust, innovation, and team cohesion.</p>
<p>The responsibility lies with leadership to drive these changes. By prioritizing small yet impactful actions — like transparent communication, collaborative role definitions, and empathetic feedback — they can transform the hiring process into one that empowers both candidates and teams. These incremental adjustments yield profound results, fostering a culture of trust and long-term success. The opportunity to transform is within reach; it’s time for leadership to take the first step.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/the-cruelty-of-hiring">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Business</category><category>Leadership</category><category>Management</category><category>Interview</category><category>Productivity</category>
    </item>
    <item>
      <title>Projects vs. Products</title>
      <link>https://zachshallbetter.com/writing/projects-vs-products</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/projects-vs-products</guid>
      <pubDate>Sun, 12 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>Understanding their distinct roles, lifecycles, and metrics to drive impactful results and sustainable innovation.</description>
      <content:encoded><![CDATA[<p>The terms “<strong>projects</strong>” and “<strong>products</strong>” are often used interchangeably, yet they represent fundamentally different approaches to delivering value. Each has its own lifecycle, metrics, and focus areas. Misunderstanding this distinction can lead to misaligned priorities, inefficient resource allocation, and unmet goals. According to the <a href="https://www.pmi.org/">Project Management Institute (PMI)</a>, poor project management results in a 9.9% loss for every dollar invested, highlighting the importance of clear boundaries and well-defined objectives.</p>
<h3><strong>Defining Projects and Products</strong></h3>
<h4><strong>What Is a Project?</strong></h4>
<p>A project is a <strong>temporary endeavor</strong> designed to achieve a specific goal, whether launching a new feature, building a website, or running a marketing campaign. It operates within a <strong>defined scope</strong>, <strong>fixed timeframe</strong>, and <strong>allocated resources</strong> such as budget, manpower, and tools. The goal is to deliver a specific outcome within these constraints.</p>
<h4><strong>Key Characteristics</strong>:</h4>
<ul>
<li><p><strong>Defined Scope</strong>: Clear objectives and deliverables.</p>
</li>
<li><p><strong>Fixed Timeframe</strong>: A set start and end date.</p>
</li>
<li><p><strong>Resource Constraints</strong>: Budget, manpower, and tools allocated for the duration.</p>
</li>
<li><p><strong>Outcome-Oriented</strong>: Focused on achieving a specific goal.</p>
</li>
</ul>
<h4><strong>Examples</strong>:</h4>
<ul>
<li><p>Developing a mobile app for a client.</p>
</li>
<li><p>Executing a marketing campaign.</p>
</li>
<li><p>Implementing a new CRM system.</p>
</li>
</ul>
<p>According to <a href="https://www.mckinsey.com/">McKinsey</a>, projects with clear objectives and constraints are 28% more likely to succeed, underlining the importance of structured execution.</p>
<h4>What Is a Product?</h4>
<p>In contrast, a product is an <strong>ongoing asset</strong> or offering designed to deliver continuous value to users. Unlike projects, products evolve over time, driven by market trends, user feedback, and business objectives. The focus is on user satisfaction and retention, with the goal of sustaining and growing value. Research from <a href="https://hbr.org/">Harvard Business Review</a> shows that products that adapt to user needs are 30% more likely to achieve long-term growth.</p>
<h4><strong>Key Characteristics</strong>:</h4>
<ul>
<li><p><strong>Evolving Scope</strong>: Continuously refined based on feedback and goals.</p>
</li>
<li><p><strong>No Fixed End Date</strong>: Lifespan depends on its ability to provide value.</p>
</li>
<li><p><strong>User-Centric</strong>: Driven by customer satisfaction and data insights.</p>
</li>
<li><p><strong>Growth-Oriented</strong>: Designed to sustain and grow over time.</p>
</li>
</ul>
<h4>Examples:</h4>
<ul>
<li><p>Netflix as a streaming service.</p>
</li>
<li><p>Trello as a SaaS tool.</p>
</li>
<li><p>A consumer goods line evolving with customer preferences.</p>
</li>
</ul>
<h3><strong>Key Differences Between Projects and Products</strong></h3>
<h4><strong>Duration and Objectives</strong></h4>
<p>Projects operate within a finite timeframe, delivering a specific result, such as launching a feature or upgrading a system. Products, on the other hand, have no fixed end date and focus on delivering sustained value by adapting to user needs and market demands.</p>
<h4><strong>Scope and Success Metrics</strong></h4>
<p>The scope of a project is defined at the outset, while product scope evolves over time based on feedback and strategic goals. Success for projects is measured by adherence to timelines, budgets, and deliverables. Product success is gauged by metrics like user satisfaction, retention, and return on investment (ROI). Companies prioritizing customer satisfaction report <a href="https://www2.deloitte.com/">25% higher profitability</a>, illustrating the importance of sustained value in product management.</p>
<h3><strong>Measurements and Metrics</strong></h3>
<h4><strong>Projects: Execution-Focused Metrics</strong></h4>
<p>Projects are assessed through metrics that measure execution and adherence to constraints. These include scope management, budget compliance, and timeline adherence.</p>
<p>Key project management concepts such as the <strong>critical path</strong>, <strong>milestones</strong>, and <strong>burn rate</strong> ensure that projects remain on track. The critical path identifies the sequence of tasks affecting the project’s completion date, helping teams prioritize. Milestones mark significant progress points, while burn rate tracks the pace of budget usage. A <a href="https://www.pmi.org/">PMI study</a> found that projects with clearly defined milestones are 36% more likely to be delivered on time, highlighting the importance of structured tracking.</p>
<h4><strong>Key Concepts</strong>:</h4>
<ul>
<li><p><strong>Scope Management:</strong> Adherence to defined requirements.</p>
</li>
<li><p><strong>Budget Compliance:</strong> Staying within financial limits.</p>
</li>
<li><p><strong>Timeline Adherence:</strong> Meeting deadlines and milestones.</p>
</li>
<li><p><strong>Resource Allocation:</strong> Efficient use of manpower and tools.</p>
</li>
<li><p><strong>Risk Management:</strong> Addressing unforeseen challenges.</p>
</li>
</ul>
<h4><strong>Products: Value-Focused Metrics</strong></h4>
<p>Product success relies on value-focused metrics that emphasize long-term user satisfaction and growth. These include user adoption, customer satisfaction (CSAT), and revenue growth.</p>
<p>Metrics like <strong>Net Promoter Score (NPS)</strong>, <strong>product-market fit</strong>, and <strong>customer lifetime value (CLV)</strong> are key to evaluating a product’s impact. NPS measures customer loyalty by asking users how likely they are to recommend the product. Product-market fit assesses how well the product meets customer needs, while CLV estimates the total revenue generated by a customer over their lifecycle. According to <a href="https://www.bain.com/">Bain &amp; Company</a>, companies with high NPS scores grow twice as fast as their competitors, underscoring the importance of user loyalty in driving success.Key Concepts:</p>
<h4>Key Concepts:</h4>
<ul>
<li><p><strong>User Adoption:</strong> Number of active users.</p>
</li>
<li><p><strong>Customer Satisfaction (CSAT):</strong> Feedback scores from users.</p>
</li>
<li><p><strong>Retention and Churn:</strong> Percentage of returning customers.</p>
</li>
<li><p><strong>Revenue Growth:</strong> Income generated by the product.</p>
</li>
<li><p><strong>Feature Utilization:</strong> Frequency of key feature use.</p>
</li>
</ul>
<h3>Lifecycle Differences</h3>
<h4><strong>Project Lifecycle</strong></h4>
<p>The project lifecycle follows a linear sequence, beginning with <strong>initiation</strong>, where the scope, objectives, and constraints are defined. Next is the <strong>planning</strong> phase, which involves developing schedules, allocating resources, and identifying risks. During <strong>execution</strong>, tasks are carried out to achieve the desired outcomes, with <strong>monitoring and control</strong> ensuring progress remains on track. Finally, the <strong>closure</strong> phase marks the delivery of final outputs, evaluation of results, and formal conclusion of the project.</p>
<p>According to the <a href="https://standishgroup.com/">Standish Group’s CHAOS Report</a>, only 35% of projects are completed successfully, emphasizing the need for clear phases and strong monitoring.</p>
<h4>Key Concepts:</h4>
<ul>
<li><p><strong>Initiation:</strong> Define scope, objectives, and constraints.</p>
</li>
<li><p><strong>Planning:</strong> Develop schedules, allocate resources, and identify risks.</p>
</li>
<li><p><strong>Execution:</strong> Carry out tasks to deliver outcomes.</p>
</li>
<li><p><strong>Monitoring and Control:</strong> Track progress and address deviations.</p>
</li>
<li><p><strong>Closure:</strong> Deliver final output, evaluate results, and officially close.</p>
</li>
</ul>
<h4><strong>Product Lifecycle</strong></h4>
<p>The product lifecycle is iterative and evolves over time. It begins with <strong>concept/discovery</strong>, where user needs are researched, and the problem is validated. During <strong>development</strong>, a minimum viable product (MVP) is created and refined. The <strong>growth</strong> phase focuses on scaling the user base, while the <strong>maturity</strong> phase emphasizes sustaining revenue and retention. If the product reaches a <strong>decline</strong> phase, it is reassessed for reinvention or retirement.</p>
<p>Research from <a href="https://www.gartner.com/">Gartner</a> shows that companies successfully pivoting or reinvesting in declining products have a 50% greater chance of regaining market share, highlighting the importance of adaptability.</p>
<p>Research from <a href="https://www.gartner.com/">Gartner</a> shows that companies successfully pivoting or reinvesting in declining products have a 50% greater chance of regaining market share, highlighting the importance of adaptability.</p>
<h4>Key Concepts:</h4>
<ul>
<li><p><strong>Concept/Discovery:</strong> Research user needs and validate the problem.</p>
</li>
<li><p><strong>Development:</strong> Build a minimum viable product (MVP) and iterate.</p>
</li>
<li><p><strong>Growth:</strong> Expand user base and optimize features.</p>
</li>
<li><p><strong>Maturity:</strong> Sustain revenue and optimize retention.</p>
</li>
<li><p><strong>Decline:</strong> Reassess for re-invention or retirement.</p>
</li>
</ul>
<p>Projects often feed into products, but their relationship must be managed strategically. Projects are ideal for discrete initiatives, such as launching a new feature or improving infrastructure. Products, however, represent the cumulative value of these initiatives, tied together by a strategic roadmap. It’s important to recognize that while projects achieve finite goals, products must continuously adapt and evolve to remain valuable. Bridging these two approaches requires clear alignment between project deliverables and product objectives.</p>
<h3><strong>Bridging Projects and Products</strong></h3>
<p>Projects often serve as the building blocks of products, but their relationship must be managed strategically. Projects are best for short-term objectives, such as launching a feature or addressing technical debt, while products represent the cumulative value of these initiatives, guided by a strategic roadmap.</p>
<p>Leaders must ensure alignment between project deliverables and product goals. For example, a project to enhance backend performance should directly support the product’s scalability. This alignment fosters a cohesive development process that delivers immediate results while supporting long-term growth.</p>
<h4><strong>Key Takeaways:</strong></h4>
<ul>
<li><p><strong>Use Projects for Specific Initiatives</strong>: Apply projects to tackle defined challenges, such as improving infrastructure, developing a new feature, or addressing short-term business needs.</p>
</li>
<li><p><strong>Treat Products as the Sum of Projects</strong>: Manage products with a strategic roadmap that integrates project outputs into a cohesive, evolving offering.</p>
</li>
</ul>
<h4><strong>Key Insight:</strong></h4>
<p>Projects achieve finite goals, while products must continuously evolve to remain valuable.</p>
<h4><strong>Mastering the Balance Between Projects and Products</strong></h4>
<p>By mastering the interplay between projects and products, leaders can drive both short-term success and sustainable innovation, ensuring impactful results in the evolving landscape of modern development. Projects offer structure and measurable outcomes, addressing specific goals within defined constraints. They act as essential building blocks for progress, delivering timely results and resolving immediate challenges.</p>
<p>Products, on the other hand, evolve continuously, adapting to user needs, market trends, and business objectives. They rely on project outcomes to fuel growth while maintaining focus on long-term value creation. Together, projects and products form a cohesive system, where short-term initiatives feed into a broader strategy that sustains relevance and fosters innovation.</p>
<p>Leaders who align project deliverables with product goals create a seamless flow from ideation to implementation, ensuring every effort serves a larger purpose. This synergy promotes collaboration, accountability, and adaptability, empowering organizations to meet today’s demands while preparing for future opportunities.</p>
<p>Ultimately, understanding and leveraging the unique strengths of both projects and products is the foundation of sustainable growth. Organizations that strike this balance will not only deliver results but also drive meaningful, lasting progress in an ever-changing landscape.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/projects-vs-products">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Product</category><category>Project management</category><category>Management</category><category>Business</category><category>Product management</category>
    </item>
    <item>
      <title>Feedback Loops</title>
      <link>https://zachshallbetter.com/writing/feedback-loops</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/feedback-loops</guid>
      <pubDate>Sat, 11 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>Turning Data Into Continuous Improvement</description>
      <content:encoded><![CDATA[<p>Feedback loops are powerful systems for refining products, processes, and workflows. They capture data, analyze trends, and create opportunities for continuous improvement. To truly harness their potential, you need not only to understand how feedback loops work but also how to track and view them effectively. This includes what data to collect, how to visualize it, and what formulas to use for actionable insights.</p>
<p>This article will walk through how to measure feedback loops, what the data looks like, and how formulas can quantify and validate improvements. We’ll also include practical examples for both digital and physical products.</p>
<h3><strong>Tracking Feedback Loops</strong></h3>
<h4><strong>Key Steps in Tracking</strong></h4>
<ol>
<li><p><strong>Identify Metrics</strong>: Define specific data points that represent success, inefficiencies, or anomalies.</p>
</li>
<li><p><strong>Set Benchmarks</strong>: Establish baseline expectations for performance.</p>
</li>
<li><p><strong>Capture Data Continuously</strong>: Automate data collection for consistency.</p>
</li>
<li><p><strong>Visualize Trends</strong>: Use dashboards, graphs, or heatmaps to reveal patterns.</p>
</li>
<li><p><strong>Correlate Inputs and Outputs</strong>: Ensure every action (input) can be measured against its results (output).</p>
</li>
</ol>
<h3><strong>What Data to Track</strong></h3>
<h4><strong>Digital Products</strong></h4>
<ul>
<li><p><strong>User Behavior</strong>: Click-through rates (CTR), bounce rates, session times, drop-off points.</p>
</li>
<li><p><strong>System Performance</strong>: Load times, error rates, server uptimes.</p>
</li>
<li><p><strong>Engagement Metrics</strong>: Completion rates, conversion rates, retention metrics.</p>
</li>
</ul>
<h4><strong>Physical Products</strong></h4>
<ul>
<li><p><strong>Production Metrics</strong>: Cycle times, defect rates, material usage, assembly times.</p>
</li>
<li><p><strong>Operational Metrics</strong>: Downtime, resource utilization, maintenance schedules.</p>
</li>
<li><p><strong>Output Metrics</strong>: Units produced, costs per unit, delivery times.</p>
</li>
</ul>
<h3><strong>How to View Feedback Loops: Unlocking Insights Through Visualization</strong></h3>
<p>Effectively viewing feedback loops requires transforming complex information into clear, actionable insights. Each visualization method plays a unique role in uncovering patterns, highlighting inefficiencies, and guiding decisions. Here’s how to use them effectively:</p>
<h4><strong>Dashboards: Real-Time Pulse on Performance</strong></h4>
<p>Dashboards provide a consolidated, interactive interface for monitoring key metrics in real time. They offer an instant overview of system health, allowing teams to identify anomalies and act quickly.</p>
<ul>
<li><p><strong>Use Case</strong>: A SaaS platform might use a dashboard to track user activity, error rates, and subscription renewals. If server downtime spikes, the dashboard flags the issue for immediate resolution.</p>
</li>
<li><p><strong>Pro Tip</strong>: Tailor dashboards to stakeholder needs — executives benefit from high-level summaries, while engineers need granular data.</p>
</li>
</ul>
<h4><strong>Graphs and Trends: Seeing Progress Over Time</strong></h4>
<p>Graphs reveal how metrics change over time, exposing trends, patterns, and deviations. They make it easier to assess whether recent changes are yielding positive outcomes.</p>
<ul>
<li><p><strong>Use Case</strong>: In e-commerce, a line graph could show the drop-off rate during checkout before and after implementing a one-click payment feature. A downward trend confirms the change’s success.</p>
</li>
<li><p><strong>Pro Tip</strong>: Annotate graphs with key events, such as feature launches, to directly link actions to results.</p>
</li>
</ul>
<h4><strong>Comparative Views: Before-and-After Insights</strong></h4>
<p>Comparative views enable side-by-side analysis of data from different periods, configurations, or user groups. This helps teams quickly evaluate the impact of changes.</p>
<ul>
<li><p><strong>Use Case:</strong> A manufacturing team might compare defect rates before and after automating a production step. A significant drop in defects confirms the value of the investment.</p>
</li>
<li><p><strong>Pro Tip:</strong> Include percentage change calculations alongside visuals to quickly convey improvement magnitude.</p>
</li>
</ul>
<h4><strong>Heatmaps: Visualizing Interaction and Friction Points</strong></h4>
<p>Heatmaps show areas of high or low activity within a user interface, workflow, or system, making it easy to pinpoint bottlenecks or usability issues.</p>
<p><strong>Use Case:</strong> A UX team could analyze heatmaps of a webpage to identify where users click most frequently. If a key call-to-action button gets little attention, its placement or design might need adjustment.</p>
<p><strong>Pro Tip:</strong> Combine heatmaps with user flow analysis to see how interactions progress through the workflow, identifying exactly where users encounter obstacles.</p>
<p>The goal is to analyze data until it provides a narrative to use in decision making and continuous improvement. Whatr the case, digital products or physical workflows, visualization is the best human means of understanding and refining feedback loops.</p>
<h3><strong>Practical Examples of Feedback Loop Tracking</strong></h3>
<h4><strong>Digital Product Example: Checkout Flow</strong></h4>
<p><strong>Goal</strong>: Reduce drop-off rates in a multi-step checkout process.</p>
<ol>
<li><p><strong>Metrics to Track</strong>: Bounce rate at each step, average time per step, error rates for form validation.</p>
</li>
<li><p><strong>Baseline Data</strong>:</p>
</li>
</ol>
<ul>
<li><p><strong>Step 1:</strong> 20% bounce rate.</p>
</li>
<li><p><strong>Step 2:</strong> 30% bounce rate.</p>
</li>
<li><p><strong>Step 3</strong>: 40% bounce rate.</p>
</li>
</ul>
<ol start="3">
<li><p><strong>Action Taken</strong>: Simplify Step 2 by reducing required fields and adding auto-complete.</p>
</li>
<li><p><strong>Formula Application</strong>:</p>
</li>
</ol>
<ul>
<li><p>Bounce Rate Improvement (Step 2) = ((30% — 20%) ÷ 30%) × 100% = 33.3% improvement.</p>
</li>
<li><p>ROI of Change = (($25,000 — $5,000) ÷ $5,000) × 100% = 400% ROI.</p>
</li>
</ul>
<ol start="5">
<li><strong>Visualization</strong>: A line graph showing bounce rates decreasing over time at each step, with annotations for implemented changes.</li>
</ol>
<p><strong>Physical Product Example: Assembly Line</strong></p>
<p><strong>Goal</strong>: Reduce material waste and improve assembly speed.</p>
<h4><strong>1. Cumulative Metrics to Track</strong>:</h4>
<ul>
<li><p>Material usage per unit</p>
</li>
<li><p>Average Assembly time</p>
</li>
<li><p>Defect rates.</p>
</li>
</ul>
<h4>2. <strong>Baseline Data</strong>:</h4>
<ul>
<li><p><strong>Material Waste</strong>: 10%.</p>
</li>
<li><p><strong>Assembly Time</strong>: 12 minutes per unit.</p>
</li>
<li><p><strong>Defect Rate</strong>: 8%.</p>
</li>
</ul>
<ol start="3">
<li><strong>Action Taken</strong>: Automate the material cutting process and train assembly staff.</li>
</ol>
<h4>4. <strong>Formula Application</strong>:</h4>
<ul>
<li><p><strong>Efficiency Improvement</strong> = ((12–9) ÷ 12) × 100% = 25% faster assembly.</p>
</li>
<li><p><strong>Defect Rate Reduction</strong>= ((8% — 5%) ÷ 8%) × 100% = 37.5% reduction.</p>
</li>
</ul>
<h4><strong>5. Visualization:</strong></h4>
<p>A bar chart comparing pre and post-automation metrics, with trend lines showing waste reduction and time savings.</p>
<h3><strong>Refining Feedback Loops Over Time</strong></h3>
<p>Refining feedback loops is a dynamic process that requires both vigilance and adaptability. The goal is to continuously evolve, using insights from each iteration to enhance performance and outcomes. Here’s how to approach it effectively:</p>
<h4><strong>Continuous Tracking</strong></h4>
<ul>
<li><p>Regularly update and review metrics to capture the impact of external factors or new changes.</p>
</li>
<li><p>Use automated tools like analytics platforms, IoT sensors, or custom dashboards to ensure consistent and accurate data collection.</p>
</li>
<li><p>Monitor key performance indicators (KPIs) in real time to detect emerging trends or potential issues before they escalate.</p>
</li>
<li><p>Incorporate external data, such as industry benchmarks or market trends, to contextualize your performance and identify opportunities for improvement.</p>
</li>
</ul>
<h4><strong>Iterative Improvements</strong></h4>
<ul>
<li><p>Treat feedback loops as iterative processes: every cycle provides new data to inform the next set of decisions.</p>
</li>
<li><p>Prioritize areas with the highest ROI, focusing on changes that deliver the most significant impact with the least resource investment.</p>
</li>
<li><p>Conduct regular retrospective analyses to evaluate the success of implemented changes and refine your approach based on lessons learned.</p>
</li>
<li><p>Foster a culture of experimentation by testing small, incremental changes before rolling out major updates, ensuring minimal disruption while validating results.</p>
</li>
</ul>
<h4><strong>Embracing Proactive Adjustments</strong></h4>
<ul>
<li><p>Predict potential bottlenecks or challenges by analyzing historical data and modeling future scenarios.</p>
</li>
<li><p>Use machine learning and predictive analytics to forecast the impact of changes, enabling more informed decision-making.</p>
</li>
<li><p>Set up alerts for critical deviations from benchmarks, ensuring teams can act proactively rather than reactively.</p>
</li>
</ul>
<h4><strong>Collaborative Optimization</strong></h4>
<ul>
<li><p>Involve cross-functional teams in feedback loop analysis to gain diverse perspectives and uncover insights that might be missed in siloed reviews.</p>
</li>
<li><p>Share data and visualizations across the organization to align stakeholders and foster a data-driven culture.</p>
</li>
<li><p>Encourage team members to propose changes and improvements, leveraging their hands-on experience for targeted enhancements.</p>
</li>
</ul>
<h4><strong>Long-Term Evolution</strong></h4>
<ul>
<li><p>Periodically reevaluate the relevance of your metrics to ensure they align with evolving business goals and market conditions.</p>
</li>
<li><p>Invest in advanced tools and technologies, such as AI-powered analytics, to stay ahead of the curve and improve data accuracy and interpretation.</p>
</li>
<li><p>Document each iteration of the feedback loop to create a comprehensive knowledge base, enabling future teams to build on past successes and avoid repeating mistakes.</p>
</li>
</ul>
<p>By continuously tracking, iterating, and proactively adjusting, you’ll ensure that your feedback loops remain a driving force for innovation and sustained improvement. Good Luck!</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/feedback-loops">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Productivity</category><category>Project management</category><category>Business strategy</category><category>Data</category><category>Business</category>
    </item>
    <item>
      <title>Guide to E-Commerce Metrics</title>
      <link>https://zachshallbetter.com/writing/guide-to-e-commerce-metrics</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/guide-to-e-commerce-metrics</guid>
      <pubDate>Fri, 10 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description></description>
      <content:encoded><![CDATA[<p>I like to document information and data and in online commerce decision hinge on analysis of data. Everything from shipping, user journeys, to optimizing operations, success is defined by our ability to measure, analyze, and act on key metrics. So I obsess a little over the details.</p>
<p>This guide unpacks the terms and measurements I’ve found useful and believe managers need to master.</p>
<h3>Core Operational Metrics</h3>
<h4>Throughput</h4>
<p>Throughput measures how efficiently your system delivers value. By tracking the number of successful transactions within a specific time frame, you can gauge your system’s capacity.</p>
<p>**Formula:**Throughput = Total Successful Transactions ÷ Time Period</p>
<p><strong>Example:</strong> Processing 10,000 orders per hour during a flash sale indicates system robustness.</p>
<h4>Cycle Time</h4>
<p>Cycle time tracks the duration required to complete a process from start to finish. Shorter cycle times mean quicker delivery of features or services.</p>
<p><strong>Formula:</strong> Cycle Time = End Time — Start Time</p>
<p><strong>Example:</strong> Reducing cycle time for checkout system updates accelerates response to customer feedback.</p>
<h4>Lead Time</h4>
<p>This metric captures the time from a customer’s initial request to the delivery of their order, providing insights into your overall operational efficiency.</p>
<p><strong>Formula:</strong> Lead Time = Delivery Time — Request Time</p>
<p><strong>Example:</strong> Maintaining lead times of under three days for expedited shipping ensures customer satisfaction.</p>
<h4>Utilization Rate</h4>
<p>Utilization rate measures the percentage of resources actively contributing to value creation, helping you balance efficiency and resource management.</p>
<p><strong>Formula:</strong> Utilization Rate = (Active Time ÷ Available Time) × 100%</p>
<p><strong>Example:</strong> During peak holiday periods, a 90% utilization rate in warehouses signals optimal staffing levels without overloading employees.</p>
<hr>
<h3><strong>Customer-Focused Metrics</strong></h3>
<h4><strong>Conversion Rate</strong></h4>
<p>The percentage of visitors who complete a desired action, such as making a purchase. A higher conversion rate reflects the effectiveness of your site design and marketing.</p>
<p><strong>Formula:</strong> Conversion Rate = (Conversions ÷ Total Visitors) × 100%</p>
<p>**Example:**Redesigning product pages increased the conversion rate from 2.5% to 4%.</p>
<h4><strong>Average Order Value (AOV)</strong></h4>
<p>AOV calculates the average amount spent per transaction, offering opportunities to adjust pricing or encourage bundling.</p>
<p><strong>Formula:</strong> AOV = Total Revenue ÷ Number of Orders</p>
<p><strong>Example:</strong> Introducing complementary product recommendations boosted AOV by 15%.</p>
<h4><strong>Customer Acquisition Cost (CAC)</strong></h4>
<p>The total cost of acquiring a new customer, including marketing and operational expenses. Managing CAC relative to lifetime value ensures profitability.</p>
<p><strong>Formula:</strong> CAC = Marketing Expenses ÷ New Customers Acquired</p>
<p>**Example:**Optimizing social media ads reduced CAC by 20%.</p>
<h4><strong>Lifetime Value (LTV)</strong></h4>
<p>LTV reflects the total revenue generated by a customer over their relationship with your business. It’s a cornerstone for long-term growth strategies.</p>
<p><strong>Formula:</strong> LTV = Avg. Purchase Value × Purchase Freq. × Customer Lifespan</p>
<p>**Example:**Loyal customers generate three times more revenue than one-time buyers.</p>
<h3><strong>Process Efficiency Metrics</strong></h3>
<h4><strong>First-Time Yield (FTY)</strong></h4>
<p>FTY measures the percentage of work completed correctly on the first attempt, minimizing rework and boosting efficiency.</p>
<p><strong>Formula:</strong> FTY = (Correct Outputs ÷ Total Outputs) × 100%</p>
<p><strong>Example:</strong> 98% of orders are packed and shipped without errors, reducing fulfillment delays.</p>
<h4><strong>Return Rate</strong></h4>
<p>Tracking the percentage of products returned reveals potential quality or fit issues.</p>
<p><strong>Formula:</strong> Return Rate = (Total Returns ÷ Total Sales) × 100%</p>
<p>**Example:**Addressing high return rates on a specific product by refining its size guide reduced returns by 25%.</p>
<h4><strong>Fulfillment Accuracy</strong></h4>
<p>This metric measures how accurately orders are fulfilled, ensuring customers receive exactly what they ordered.</p>
<p><strong>Formula:</strong> Fulfillment Accuracy = (Accurate Orders ÷ Total Orders) × 100%</p>
<p><strong>Example:</strong> Achieving 99% fulfillment accuracy through automated picking systems.</p>
<h3><strong>Risk and Variability Metrics</strong></h3>
<h4><strong>Failure Rate</strong></h4>
<p>Failure rate tracks the frequency of errors or breakdowns in systems and processes.</p>
<p><strong>Formula:</strong> Failure Rate = (Failed Transactions ÷ Total Transactions) × 100%</p>
<p><strong>Example:</strong> A 1% payment failure rate due to outdated card details highlights the need for better card expiry notifications.</p>
<h4><strong>Standard Deviation</strong></h4>
<p>A measure of variability, standard deviation helps identify consistency in performance metrics like delivery times or website load speeds.</p>
<p><strong>Formula:</strong> Standard Deviation = √(Σ(xᵢ — μ)² ÷ n)</p>
<p><strong>Example:</strong> Reducing delivery time variability improves reliability, fostering customer trust.</p>
<h4><strong>Outlier Analysis</strong></h4>
<p>By identifying anomalies, outlier analysis can uncover hidden issues or opportunities.</p>
<p><strong>Formula:</strong> No direct formula (depends on statistical approach)</p>
<p>**Example:**Investigating a sudden conversion drop during a promotion revealed a misconfigured discount code.</p>
<h4><strong>Total Failures</strong></h4>
<p>Understanding the impact of total system breakdowns helps in planning robust contingency workflows.</p>
<p><strong>Formula:</strong> Total Failures = Sum of System Breakdowns</p>
<p><strong>Example:</strong> Implementing redundancy for server outages to prevent downtime during peak sales.</p>
<h3><strong>Experience Metrics</strong></h3>
<h4><strong>Net Promoter Score (NPS)</strong></h4>
<p>NPS measures customer loyalty and the likelihood of recommendations.</p>
<p><strong>Formula:</strong> NPS = % Promoters — % Detractors</p>
<p><strong>Example:</strong> Simplifying the return process increased NPS by 10 points.</p>
<h4><strong>Cart Abandonment Rate</strong></h4>
<p>This metric tracks the percentage of users who add items to their cart but leave without purchasing.</p>
<p><strong>Formula:</strong> Abandonment Rate = (Carts Abandoned ÷ Carts Created) × 100%</p>
<p><strong>Example</strong>: Reducing abandonment by offering guest checkout and multiple payment options.</p>
<h4><strong>Bounce Rate</strong></h4>
<p>The percentage of visitors leaving after viewing just one page. A high bounce rate may indicate issues with page relevance or content.</p>
<p><strong>Formula:</strong> Bounce Rate = (Single-Page Visits ÷ Total Visits) × 100%</p>
<p><strong>Example</strong>: Improving homepage clarity reduced the bounce rate by 20%.</p>
<h4><strong>Time to Purchase</strong></h4>
<p>Time to purchase measures how long a visitor takes to complete a transaction, offering insights into your checkout process.</p>
<p><strong>Formula:</strong> No direct formula (tracked as time from first site visit to completed transaction)</p>
<p><strong>Example</strong>: Streamlining checkout flow cut time to purchase by 40%.</p>
<h3><strong>Financial and Strategic Metrics</strong></h3>
<h4><strong>Gross Merchandise Value (GMV)</strong></h4>
<p>GMV represents the total revenue generated before expenses, offering a snapshot of overall sales performance.</p>
<p><strong>Formula:</strong> GMV = Total Sales Price × Units Sold</p>
<p><strong>Example</strong>: Reaching $1M GMV in Q4 through targeted holiday campaigns.</p>
<h4><strong>Cost of Delay (CoD)</strong></h4>
<p>CoD quantifies the financial impact of delays in product launches or feature rollouts.</p>
<p><strong>Formula:</strong> CoD = Estimated Daily Revenue × Days Delayed</p>
<p><strong>Example</strong>: Postponing a winter clothing line launch cost $10K in lost revenue.</p>
<h4><strong>Refund and Dispute Rate</strong></h4>
<p>This metric tracks the percentage of orders refunded or disputed, helping identify operational issues.</p>
<p><strong>Formula:</strong> Refund Rate = (Refunded/Disputed Orders ÷ Total Orders) × 100%</p>
<p><strong>Example</strong>: Addressing shipping delays reduced dispute rates by 15%.</p>
<h4><strong>Traffic Source Attribution</strong></h4>
<p>Understanding where your site traffic originates helps refine marketing strategies and budgets.</p>
<p><strong>Formula:</strong> No direct formula (tracked via analytics tools)</p>
<p><strong>Example</strong>: Organic search traffic converted at 2x the rate of paid ads.</p>
<h3><strong>Strategic Actions</strong></h3>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/guide-to-e-commerce-metrics">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Ecommerce</category><category>Management</category><category>Business</category><category>Technology</category><category>Project management</category>
    </item>
    <item>
      <title>Sisyphus Discovers Tools</title>
      <link>https://zachshallbetter.com/writing/sisyphus-discovers-tools</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/sisyphus-discovers-tools</guid>
      <pubDate>Thu, 09 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>A Parable of Burden, Risk, and the Absurd</description>
      <content:encoded><![CDATA[<p><em>My shoulders and legs hurt</em>. I’ve spent more days than I can count trying to shoulder the burdens of others, hauling what feels like a massive boulder up a slope that never levels out. Each time I near the top, I falter — the rock slips from my hands and crashes back down into the valley with a thunderous, mocking roll. Over and over, I scramble down to retrieve it, determined not to let anyone else suffer. My body aches, but worse is the slow erosion of my spirit: an endless loop of fatigue, guilt, and resignation.</p>
<p>*Yet, I wonder if selflessness alone is enough… Another part of me shuddered at the thought.*Must I find a different way to carry out my resolve without crushing myself or can I carry this forever. Just yesterday, a warped but sturdy limb from an olive tree caught my eye. A tool, if I dared see it as such. A secret part of me imagined using it to ease the weight, redistributing the load so I could keep going without collapsing. Another part of me shuddered at the thought: <em>Am I allowed to make this easier on myself, even if I’m doing it for others?</em> Maybe I was meant to prove my worth through suffering alone — to ease those I care for.</p>
<p>Before the branch, my days had settled into a routine. I’d gather every weight others cast aside — their pleas, their problems, their anxieties — pack them on my back and brace my tired shoulders against it, convinced it was my duty to push it up this treacherous incline. Each time, the crushing load slipped away at the last moment, without relief. The cycle was maddening, but it felt virtuous. After all, there’s honor in selflessness — <em>right</em>?</p>
<p>On those days, the sky almost always looked leaden, the clouds refusing to part. The air of the world itself reflected my sense of responsibility: chilling gusts of wind would whip against me, hinting that a downpour was just around the corner. Every step I took felt heavier, as if the gloom in the air clung to my clothes and seeped into my bones. When the sun threatened to break through, I rarely lifted my gaze to notice; my eyes remained fixed on the looming slope, on what I hadn’t accomplished.</p>
<p>Then I spotted a twisted olive branch in the dust — nothing extraordinary, yet it shifted my posture. The idea that it <em>might</em> change something. In that moment, the day’s toil was no longer a foregone conclusion — it was my choice. The idea of a tool — an easier method, a strategy to lighten the weight — transformed my suffering. If I dared to adapt, and chose to face of whatever fate I believed was ordained for me, things might improve. <em>It was hope, in options.</em></p>
<p>In that moment, I swear the wind died down for a heartbeat. The thick cover of clouds thinned, allowing a single beam of sunlight to graze the dusty ground. It felt symbolic: a fleeting hint that, even on the darkest days, there might be a crack in the sky. I could almost hear the rumble of distant thunder, as though the heavens themselves bristled at my discovery. But for the first time, instead of cowering under the threat of another storm, I found myself stirred by a rebellious hope. <em>If I was destined to be drenched, so be it — better to feel rain on my skin than walk in a gray haze, resigned and unseeing.</em></p>
<p>The breeze tugged at my clothes like a gentle reminder that change was possible. The storm clouds above churned, but they no longer felt like another glancing punishment challenging me to fail again. With the makeshift lever in hand, I realized I wasn’t just pushing a boulder; I was daring to push against the fate I’d once accepted. Every raindrop that fell now seemed more like a cleansing force than a sentence of doom. In that small shift of perception, I felt something I hadn’t in ages: a spark of control.</p>
<p>Part of me still feared the sky might split open in disapproval. Yet, in that quiet pause between gusts, another thought emerged: <em>What if rebellion isn’t about escaping my burden, but transforming the way I carry it?</em> Maybe this sentence wasn’t etched in stone so much as in my own belief that suffering must be solitary and unrelenting. Maybe, just maybe, I was allowed to discover tools, adopt new strategies — even lean on others when the weight grew too great.</p>
<p>And so, under that fractured canopy of storm clouds and sunlight, I gripped the lever more tightly. Something deep inside me settled: a calm, resolute awareness that I had the right to try — and fail if I must — rather than slog forward in half-blind resignation. <em>If thunder was the price of this revelation, endurance was the reward.</em></p>
<p>In that half-lit space, with the wind rolling back in, I squared my shoulders, braced the lever against the boulder, and whispered to myself: <em>I can do this differently.</em> I planted my feet more firmly, braced the limb against the boulder, and wondered if maybe, for the first time, I had permission to protect my own well-being without abandoning my resolve to help others. <em>What do I have to lose?</em></p>
<p>What followed wasn’t triumph or liberation. The boulder still loomed, its weight just as daunting. The slope remained steep and unwelcoming. Yet the air carried a quiet shift — a secret pact, it seemed, between the sky, the earth, and me. My heart and body loosened, untensing as the approaching storm seemed to relent, granting me this fragile moment. A challenge, perhaps, to see how I might adapt. If lightning struck, I’d welcome the spark of clarity it offered. If the rains fell, I’d let them wash the salt and sweat from my eyes, clearing my vision and revealing the path ahead.</p>
<p>It soon became clear that the real danger wasn’t in the branch snapping or the boulder growing heavier. It was in the unsettling realization that I might not be as powerless as I had once believed. That thought, daring and fragile, began to fracture the numb acceptance that had carried me this far. Who am I if I can shift this boulder — even for a moment — and what if I’m unprepared for the weight of either success or failure? Each time my fingers tighten around that makeshift lever, I find myself standing at the edge of this question, suspended between a pulse of hope and a jolt of fear.</p>
<p>And yet, I press on. For in breaking my old, defeatist patterns, I glimpse something wholly unexpected: the possibility that I can carry these burdens differently —<em>I can see options, suffer less, and still remain steadfast… What do I have to lose?</em></p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/sisyphus-discovers-tools">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      <category>Philosophy</category><category>Short story</category><category>Art</category><category>Self improvement</category><category>Writing</category>
    </item>
    <item>
      <title>Orchestrating Tomorrow</title>
      <link>https://zachshallbetter.com/writing/orchestrating-tomorrow</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/orchestrating-tomorrow</guid>
      <pubDate>Thu, 09 Jan 2025 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>The Alchemy of Humans + AI Propelling Production</description>
      <content:encoded><![CDATA[<p>In a tidy loft overlooking a bustling cityscape, an early-morning stand-up begins. Jana, a newly appointed product leader at a mid-sized tech startup, scans the virtual faces on her screen: a front-end designer in Tokyo sipping matcha, a machine-learning engineer in a Berlin café, a brand strategist in a London home office. Together, they engage in a seamless ballet of expertise — code snippets, design mockups, user interviews, and strategic insights interwoven like a symphony.</p>
<p>This is modern product leadership: dynamic, cross-functional, and deeply collaborative. The product leader is no longer a traditional “manager” but a conductor, orchestrating an evolving ecosystem of tools, interfaces, and documentation. As AI-driven tools reshape the digital landscape — spinning up websites and prototypes in minutes — the focus shifts from how to build to why and for whom. Human intuition and empathy remain the cornerstone, ensuring that technology serves not only its function but also its meaning.</p>
<h3><strong>From Frontier to Frameworks</strong></h3>
<p><strong>A Brief History of Shifting Roles</strong></p>
<p>Not long ago, building for the web felt like exploring uncharted territory. The screech of a dial-up modem risked waking the household, while text-based bulletin boards lured the curious into a fledgling digital frontier. Assembling a webpage in raw HTML was both frustrating and exhilarating — a thrilling experiment in a medium brimming with untapped potential. In those early days, tech pioneers like Amazon built their empires atop languages like Perl, which now lingers as a niche tool beloved by loyalists.</p>
<p>As the web matured, chaos gave way to structure. Tim Berners-Lee’s World Wide Web Consortium (W3C) introduced foundational standards — HTML, CSS, and accessibility guidelines — that provided a blueprint for usability and consistency. Google, with its PageRank algorithms and mobile-first indexing, emerged as the gatekeeper of visibility, shaping web practices and sparking a race to optimize site speed, embed meta tags, and adopt responsive designs. JavaScript, once a supporting player, evolved into a central force, enabling dynamic single-page applications through frameworks like Angular, React, and Vue.</p>
<p>Meanwhile, design transformed from an afterthought to a strategic pillar as user expectations skyrocketed. It wasn’t enough for websites to function; they had to offer seamless, intuitive experiences. By the early 2000s, Content Management Systems (CMS) like WordPress and Drupal lowered technical barriers, allowing non-experts to publish and manage content. Specialists, however, remained indispensable — front-end developers refining CSS, back-end engineers optimizing databases, and designers crafting interfaces.</p>
<p>Fast-forward to the 2020s, and the rise of no-code platforms like Webflow, Squarespace, and Shopify democratized web creation further. According to Gartner, no-code/low-code adoption grew by over 25% annually from 2015 to 2023, empowering everyday creators to build professional-grade digital products without needing technical expertise.</p>
<p>Yet as technological barriers dissolve, new challenges emerge: <em>If anyone can build, what makes a product stand out?</em> The answers lie not in tools but in intention. To create digital experiences that resonate, builders must interrogate their choices — what’s meaningful, what’s ethical, and how to balance innovation with humanity. Success in this new era demands a shift in focus: from simply enabling access to crafting thoughtful, purpose-driven solutions.</p>
<h4><strong>The Fulcrum of Change: From Builders to Visionaries</strong></h4>
<p>As the web has matured, its technical challenges have diminished. Frameworks, automation, and no-code tools have streamlined processes once considered Herculean. But as the barriers to building fall, a new challenge emerges: meaning. In a world where nearly anyone can create, the question is no longer <em>how</em> but <em>why</em>. What makes a product resonate? How do we ensure that digital experiences are not only functional but profoundly human?</p>
<p>This shift marks a critical inflection point for leadership in technology. The role of the builder has evolved into that of the architect, and now, into something greater: the <em>Product Orchestrator</em>. These leaders don’t merely manage projects or steer sprints; they navigate an intricate web of people, tools, and insights to create harmonious, impactful solutions.</p>
<h4><strong>The Rise of the Product Orchestrator: Leadership at the Forefront</strong></h4>
<p>In this new ecosystem, the most profound challenges aren’t technical. They’re human, strategic, and deeply creative. Enter the <em>Product Orchestrator</em>, a term that encapsulates the essence of modern product leadership. Like conductors in a symphony, these leaders can read and write music but choose to guide the entire performance instead of playing each note.</p>
<p>The power of a Product Orchestrator lies in their ability to transcend technical fluency. They understand the limitations of their tools and know how to elevate others. Much like John Williams, who orchestrates brass, strings, and percussion to produce cinematic masterpieces, Product Orchestrators weave together UX, development, marketing, and data science to achieve cohesive outcomes.</p>
<p>Consider Danny Elfman, whose violin, guitar, and piano skills inform his dynamic compositions, or Hans Zimmer, who masterfully blends piano, synthesizers, and percussion to create emotionally resonant soundscapes. These composers don’t play every instrument themselves; they empower virtuosos to interpret their vision. Product Orchestrators, similarly, rely on their teams’ expertise while ensuring every piece serves the broader composition.</p>
<p>They embody a rare duality: a connection to the fundamentals — akin to a violinist anchoring the orchestra — and a willingness to adopt new tools, from digital tape decks to cutting-edge soundboards. This balance enables them to transform potential into performance, crafting products as intuitive and timeless as a beloved melody.</p>
<p>At its core, the role of the Product Orchestrator is about intention. By combining technical expertise with strategic foresight, these leaders deliver results grounded in experience and shaped by vision. They don’t just guide; they define the experience, ensuring it resonates deeply in a world increasingly saturated with noise.</p>
<h3><strong>The Active Fine-Tuning Architecture</strong></h3>
<p>A pivotal responsibility of the Product Orchestrator lies in designing a product architecture that not only meets current needs but anticipates future growth and evolution. Jana, our archetypal orchestrator, exemplifies this approach. She immerses herself in system diagrams, scrutinizing data flows and service dependencies to ensure the product is scalable, efficient, and resilient. Her goal: align backend services with frontend experiences, eliminating friction points that might erode user satisfaction and addressing gaps in planning before they become obstacles.</p>
<p>But Jana’s work doesn’t stop at functionality. She actively fine-tunes the architecture, considering edge cases, optimizing microservices, and collaborating with her team to harness emerging technologies such as AI and real-time analytics. Her vision is to craft a system that isn’t just robust but elegant — one that invites creativity and productivity from designers, coders, and data scientists alike.</p>
<p>Her approach embodies a critical balance: ensuring the system is resilient enough to handle today’s demands while remaining flexible for tomorrow’s innovations. Whether it’s streamlining workflows or planning for rapid deployment, Jana builds with intention, creating a seamless environment where expertise converges within the windows of time her team defines.</p>
<h3><strong>Living Documentation</strong></h3>
<p><strong>The Engine of Alignment</strong></p>
<p>Jana’s leadership — and the project itself — thrives on her ability to transform intricate details into an active framework that shapes workflows and fosters alignment. For her, documentation isn’t a static archive but a dynamic, evolving system that empowers her team and drives AI-enabled tools. By systematically capturing technical details, user insights, and ethical considerations, she ensures every decision is accessible, actionable, adaptable — and most importantly, verifiable.</p>
<p>When a new feature is proposed, a repeat problem, or future ideas, Jana meticulously documents its technical architecture, implications, and anticipated user impact in a format optimized for both human understanding and machine interpretation. Developers rely on this documentation to refine the codebase, while AI systems use it to generate code, run tests, monitor performance, and suggest improvements.</p>
<p>This living documentation evolves in lockstep with the product. Version-controlled and managed like the code itself, it integrates real-time feedback from both the team and AI systems. As the product iterates, the documentation captures lessons learned, highlights emerging risks, and aligns shifting priorities. Jana’s approach ensures that human expertise and AI capabilities work in harmony, fostering a seamless, adaptive development process that breaths with the project and team.</p>
<h3><strong>A Day in the Life</strong></h3>
<p><strong>An example of how this might work</strong></p>
<p>The role of the Orchestrator goes beyond managing tasks or reviewing deliverables. It’s about fostering collaboration, aligning tools and processes, and ensuring the team stays laser-focused on delivering user-centered, high-quality products. From morning stand-ups to end-of-day ethical reviews, every action drives seamless progress across the product lifecycle.</p>
<h4><strong>(8:00 AM): Morning Stand-Up: Strategic Clarity</strong></h4>
<p>The day begins with a stand-up that’s anything but routine. “What user insights from yesterday challenged our assumptions?” This isn’t a status update — it’s an alignment session. Blockers are dissected, timelines recalibrated, and risks surfaced. By the end, every team member knows their role in advancing the product, and a mental map of the day’s potential challenges takes shape.</p>
<h4><strong>(10:00 AM): Cross-Functional Collaboration with Teeth</strong></h4>
<p>Mid-morning involves a fast-paced session with the data science lead to analyze an AI-powered recommendation engine. This isn’t just theoretical — it’s a deep dive into data, probing model assumptions, scrutinizing outputs, and weighing performance trade-offs. Potential biases in training sets are flagged to ensure inclusivity is core. “What’s the business case for tuning this threshold?” she asks, driving alignment between user impact and strategic growth. Decisions here ripple across the roadmap, influencing how the feature scales within the broader product ecosystem.</p>
<h4><strong>(1:00 PM): Mentorship Rooted in Results</strong></h4>
<p>In the afternoon, she mentors a junior engineer grappling with a critical architectural decision. Together, they evaluate competing frameworks, comparing scalability, learning curves, and compatibility with the existing stack. Rather than providing direct answers, she guides the engineer through system diagrams and key metrics, enabling them to visualize long-term impacts. By the end of the session, the engineer has a clear path forward and greater confidence, while she gains insight into knowledge gaps, informing future training initiatives.</p>
<h4><strong>(3:30 PM): Design Review with Precision</strong></h4>
<p>Later, alongside the creative team, she participates in a design review with the Interaction Strategist, assessing AI-generated prototypes shaped by iterative user feedback. But there’s no rubber-stamping. “Does this micro-interaction feel intentional? Is the accessibility testing thorough enough for real-world edge cases?” she asks, balancing big-picture flow with pixel-level scrutiny. Past user behavior informs her perspective, ensuring the interface exceeds usability standards and delivers not just functionality but delight.</p>
<h4><strong>(5:00 PM): Tactical Ethical Alignment</strong></h4>
<p>The day winds down with a high-stakes review alongside compliance and legal leads. Armed with insights from AI-driven risk assessments, she addresses data retention, transparency, and international regulatory challenges. “How do we de-risk this while maintaining speed to market?” she asks, steering the team toward pragmatic, actionable solutions. Key decisions are documented in real time, creating a clear trail for accountability and future reference.</p>
<h4><strong>Real Impact: Direction and Momentum</strong></h4>
<p>The work doesn’t end with the final meeting. There are follow-ups to field, documentation to review, and priorities to map for tomorrow. Her meticulous oversight ensures no deliverable slips through the cracks.</p>
<p>She isn’t just a facilitator — she’s a force multiplier. Whether untangling complex product challenges or negotiating trade-offs with stakeholders, her leadership keeps the gears turning. By blending technical insight with human intuition, she ensures the product evolves with clarity, purpose, and momentum. Her role isn’t glamorous — it’s gritty, demanding, and essential. But that’s where real leadership thrives: at the intersection of vision, execution, and relentless forward motion.</p>
<h3><strong>Specialists Reimagined</strong></h3>
<p><strong>From Fragmentation to High-Impact Collaboration</strong></p>
<p>This approach doesn’t eliminate specialists; it reimagine their role as indispensable anchors for turning lofty ideas into reality. A machine learning engineer at Spotify, for example, doesn’t just tinker with algorithms in isolation. They craft hyper-personalized user experiences, seamlessly blending data science with the brand’s emotional promise: discovery and joy through music. Their work is deeply impactful, connecting technical precision with human emotion.</p>
<p>In a Deloitte study of 1,200 global companies undergoing digital transformation, over 70% reported that siloed teams hindered innovation. Today’s specialists, however, operate as “consultative partners.” They bring depth of expertise while remaining aligned with the broader mission:</p>
<blockquote>
<p>“Specialists are the architects of precision, solving problems that generalized tools cannot address.”</p>
</blockquote>
<p>The intent is to ensure that big-picture thinking remains grounded, raising red flags about performance constraints, security vulnerabilities, or mismatches that could derail ambitious projects.</p>
<p><strong>Bridging Deep Expertise</strong></p>
<p>These new roles are designed to bridge disciplines and ideas, grounded in a deep understanding of each domain, while aligning with new agentic toolsets. These leaders are not mere project managers — they are skilled collaborators with technical fluency, navigating fields like UX, development, and data science to strategically align efforts.</p>
<p>Their purpose remains consistent: to bring the team together in delivering exceptional products. But their technical expertise adds depth, enabling them to challenge assumptions, synthesize diverse insights, and amplify the contributions of their specialist partners.</p>
<p>In this ecosystem, every role matters. Whether you’re a Product Orchestrator or a Specialist, each contributes to a unified system where collaboration replaces fragmentation. The Orchestrator leverages their broad yet technical perspective to empower specialists, ensuring every effort aligns with the larger vision. Together, they create not just functional products but transformative experiences that leave a lasting impact.</p>
<h3><strong>Humans + Machine</strong></h3>
<p><strong>Amplifying Creativity and Purpose</strong></p>
<p>Let’s cut to the chase: automation isn’t just about innovation; it’s about cold, hard business realities — time, money, and market dominance. AI tools promise faster turnarounds and cheaper workflows, pushing businesses to embrace efficiency at all costs. But here’s the danger: the rush for speed and savings can leave creativity, ethics, and quality in the dust. The real challenge is this — how do we leverage these tools without sacrificing what makes a product valuable? It’s a choice, and we have the power to shape it.</p>
<h4><strong>Accelerating Without Losing Depth</strong></h4>
<p>Automation offers speed, but speed without direction is wasted effort. By automating tasks like regression testing, content tagging, and scaffolding code, teams can deliver faster, yes — but only if they reinvest that saved time wisely. Developers should focus on architectural breakthroughs, not just faster deployment. Designers can push boundaries instead of simply iterating quicker. AI should accelerate meaningful work, not just churn out output. The business choice? Use speed to amplify depth, not cut corners.</p>
<h4><strong>Turning Data into Strategic Value</strong></h4>
<p>Data drives decisions, but only when it’s actionable. AI removes bottlenecks by automating data preprocessing, enabling faster insights. Yet the true value isn’t in the raw data — it’s in interpreting and applying it strategically. AI can surface correlations and flag anomalies, but it’s human expertise that identifies what’s relevant, creating strategies that move the needle. The smart business move? Let AI handle the grunt work, but keep human intuition at the helm to turn insights into impact.</p>
<h4><strong>Protecting Brand and Trust</strong></h4>
<p>AI can optimize engagement and revenue, but left unchecked, it risks eroding trust — reinforcing biases, spreading misinformation, or crossing ethical lines. When users lose trust, businesses lose money. Ethical oversight isn’t just a moral decision; it’s a financial one. Leaders need to ask: *Are we prioritizing short-term gains over long-term brand equity? Are we building systems that align with our values?*The choice is clear — invest in ethics now, or pay the price later in lost credibility and user loyalty.</p>
<h4><strong>Purpose as a Competitive Advantage</strong></h4>
<p>What sets your product apart? Automation might make the process faster, but it’s purpose that makes it resonate. As Douglas Engelbart said, “The better we get at getting better, the faster we will improve.” Businesses that use AI to scale empathy, drive ethical decisions, and create emotionally resonant products will outperform those focused solely on efficiency. Purpose isn’t a luxury — it’s a competitive advantage.</p>
<h4><strong>Final Thoughts</strong></h4>
<p>As the boundaries between front-end, back-end, AI, and design blur, it’s the skills of orchestration, empathy, and ethical discernment that define modern leadership. The hum of a dial-up modem may be a relic, but the spirit of exploration remains alive. We stand at an ever-shifting frontier, where evolving roles and emerging tools shape the digital landscapes of tomorrow.</p>
<p>The challenge isn’t merely leveraging tools; it’s doing so with purpose. True innovation uplifts and empowers the human beings at the core of every product. In this new age of product leadership, technology becomes the brush, empathy the canvas, and leaders the artists of a shared future, painting a world driven by vision, ethics, and impact — one insight at a time.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/orchestrating-tomorrow">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>The Way of the Cactus</title>
      <link>https://zachshallbetter.com/writing/the-way-of-the-cactus</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/the-way-of-the-cactus</guid>
      <pubDate>Tue, 14 Nov 2023 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>Cultivating resilience on the digital dunes</description>
      <content:encoded><![CDATA[<p>Welcome to the information desert, a vast and uncharted terrain stretching beyond the horizon. The sun above radiates unyieldingly, symbolizing the constant flow of tasks, information, and glowing digital stimuli. Each beam competes for your attention, begging for absorption from your already taxed mind. The dry wind swirls tiny grains of sharp sand, each a piece of data, a pixel of information, a task, a buzz, a noise.</p>
<p>In this harsh environment, your role is to endure and thrive.</p>
<h4>Exposure</h4>
<p>Like a desert flash flood, the rush of data is overwhelming and transient. Meaningful content is rare amidst overwhelming information, leaving one searching for lasting insight. This constant connectivity, akin to the relentless heat of a desert day, threatens to sap your focus. The cold, still nights of information scarcity challenge you to conserve your mental energy.</p>
<p>In moments of information scarcity, akin to the desert’s calm, still nights, you face a different challenge. As the digital landscape grows quiet and calm, you conserve your creative and mental resources, similar to how a cactus conserves water. Yet, this quietude can bring a sense of disconnection, leaving you yearning for the day’s interactive warmth and the connections it offers.</p>
<h4>Sunwise</h4>
<p>As you transition from these extremes, visualize yourself beneath the digital desert’s vast sky, enduring the unyielding blaze of the information sun. Like the desert sun’s rays, the data stream brings potential distractions at every turn. Developing a resilient ‘skin’ akin to a cactus, you’ve learned to filter and reflect these digital rays. This strategy extends beyond mere endurance; it’s about thriving strategically amidst digital adversity.</p>
<p>Contemplate the primary distractions in your digital life — social media, emails, continuous news feeds. How can you strategically lessen their impact? Setting specific times for social media, turning off persistent notifications, or unsubscribing from unnecessary newsletters act as your protective layers, much like a cactus’s skin, allowing you to absorb the benefits while shielding from the overwhelming.</p>
<p>As you find this balance, you survive the digital desert’s harsh climate and thrive in it. You learn to harness the intense energy of technology for growth and creativity, turning potentially draining experiences into opportunities for deep work and reflection.</p>
<h4>Reservoirs of Knowledge</h4>
<p>In mastering digital temperance, envision transforming the constant data flow into a nurturing force. Imagine cultivating a mental oasis of productivity and peace within. In this sanctuary, you gather information as a cactus collects raindrops, storing each valuable insight for when it’s most needed. Like the cactus’s fruit, your ideas are allowed to germinate and mature, becoming ready to nourish and share at the right moment.</p>
<p>True innovation doesn’t spring from the brief showers of trends but from deep, thoughtfully preserved understanding. With a mind free from the relentless rush of data, picture the space you’ve created for synthesis and lasting innovation.</p>
<p>Reflect on your approach to managing the daily influx of information. What practices can you adopt to curate your reservoir of knowledge, ensuring you select and store only what contributes to your long-term growth and creativity?</p>
<h4>Ecosystems</h4>
<p>Like the cactus, isolated in the digital desert, your knowledge and peace are shared with those around you, nurturing growth and fostering a community that thrives on collective wisdom. Deep work in this context goes beyond personal achievement; it’s about enriching others with your gathered wisdom.</p>
<p>Adaptability becomes crucial in this environment. At times, you may need to expend your carefully hoarded resources to navigate the shifting sands of technology. Envision yourself bending and swaying with the gales of change yet staying rooted in your core principles, exemplifying resilience.</p>
<p>This adaptability can lead to unexpected collaborations, akin to the desert flora thriving against all odds. Through these collaborative oases, unite diverse skills and insights, paving the way for groundbreaking innovations. The synergy of your collective efforts, focused and refined, flourishes into friendships, creativity, and progress.</p>
<h4>The Solitary Saguaro</h4>
<p>In the immensity of the digital desert, consider the importance of moments akin to those of a solitary saguaro — times of stillness and disconnection. These periods of stepping back from the digital world are like the calm of a desert night, offering rejuvenation and a break from the information deluge. This deliberate retreat mirrors the saguaro’s quiet resilience, where stillness becomes a crucible for creativity and problem-solving.</p>
<p>In these moments of solitude, you do more than escape the data flood; you enter a contemplative space reminiscent of the saguaro’s peaceful solitude. Your thoughts can meander in quietness, drawing deeply from your mental reservoirs. Here, insights and inspirations flourish in the fertile silence of introspection and deep reflection.</p>
<p>Think about how you can incorporate periods of solitude into your digital routine. How can you create intentional pauses, moments akin to the desert’s tranquil nights, to nurture your cognitive landscape and allow for the emergence of profound, introspective thoughts?</p>
<h4>Cool Evenings</h4>
<p>As the day’s heat radiates away, imagine the onset of cool evenings in the digital desert. These periods offer a respite from the scorching intensity of information, a time to step back and refresh your mind. As you relish the cooler air after a hot day, embrace the opportunity to pause, breathe, and disconnect from the constant digital stimuli.</p>
<p>Consider adopting strategies to disengage from your screens and responsibilities. Perhaps establish a ‘digital sunset’ when you consciously disconnect from digital devices and focus on more enriching activities.</p>
<p>Engage in mindful practices to process the day’s experiences, insights, and emotions, fostering a deeper connection with yourself and your surroundings. These cool evenings are not just for rest; they are opportunities for growth in various dimensions of your life. Whether reading, spending quality time with loved ones, socializing, or simply enjoying quietude, these activities can recharge your creativity and enthusiasm, preparing you for the next day&#39;s challenges.</p>
<h4>The Longest Life</h4>
<p>Finally, reflect on the cactus thriving in the harshest environments, a powerful symbol for your approach to the digital age. It embodies the principles of selective absorption, intentional focus, and disciplined cultivation — critical strategies for managing data deluge and maintaining a healthy mental oasis.</p>
<p>As you ponder the insights from this article, consider how these principles apply to your digital and intellectual life. What information is precious for your personal and professional growth? How can you cultivate a habit of selective attention and purposeful work to sift through the noise and focus on what’s essential? And how can you consistently nourish your intellectual growth with a disciplined approach?</p>
<p>You are adopting the characteristics of the cactus in your approach to information and technology, which positions you to survive and thrive amidst the vastness of the digital desert. This mindset empowers you to transform an overwhelming world of information into a source of sustenance, driving your intellectual and professional evolution.</p>
<p>In the ever-shifting sands of the digital desert, let the resilience and adaptability of the cactus be your guide, transforming each challenge into an opportunity for growth and each piece of information into a stepping stone toward a flourishing oasis of wisdom and creativity.</p>
<hr>
<blockquote>
<p>On the digital dunes, under the cyber sun’s glow,Stands a cactus, resilient, where data streams flow.Amidst bytes and tasks, it filters with care,Thriving in landscapes both overwhelming and bare.</p>
</blockquote>
<blockquote>
<p>Amid the data’s rush, it judiciously sifts,Conserving insight as the digital tide shifts.Shielding its core from the glare of excess,Nurturing fruits that it individually selects.</p>
</blockquote>
<blockquote>
<p>In the quiet of night, when the flow ebbs away,The cactus conserves, awaiting the day.In the vastness of dunes, where the cyber sun shines,It teaches us prudence in these digital times.</p>
</blockquote>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/the-way-of-the-cactus">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>Middleware in Next.js: A Comprehensive Guide</title>
      <link>https://zachshallbetter.com/writing/middleware-in-next-js-a-comprehensive-guide</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/middleware-in-next-js-a-comprehensive-guide</guid>
      <pubDate>Fri, 29 Sep 2023 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>Note: This article is a personal reference guide — results may vary!</description>
      <content:encoded><![CDATA[<blockquote>
<p>Note: This article is for personal reference — results may vary!</p>
</blockquote>
<p>Middleware in Next.js is a powerful tool that allows developers to intercept, modify, and control the flow of requests and responses in their applications. Whether you’re building a server-rendered website or a full-fledged web application, understanding how to use Middleware effectively can significantly enhance the data flow in and out of your project. This guide will explore Middleware in Next.js, from the basics to advanced techniques.</p>
<blockquote>
<p>Complete examples can be found in the associated Gist. You can find them here: <a href="https://gist.github.com/zachshallbetter/ee164b1f2842a3aee5caabaf4e375ae3">https://gist.github.com/zachshallbetter</a>.</p>
</blockquote>
<h3>Table of Contents</h3>
<ul>
<li><p>Understanding Middleware</p>
</li>
<li><p>Getting Started with Middleware</p>
</li>
<li><p>Middleware in Next.js</p>
</li>
<li><p>Advanced Middleware Techniques</p>
</li>
<li><p>Middleware Upgrade Guide</p>
</li>
</ul>
<hr>
<h3>1. Understanding Middleware</h3>
<h4>What is Middleware?</h4>
<p>When building a site or application for the web, middleware is a valuable concept to understand. The quick version — Middleware provides a mechanism for intercepting and manipulating the various aspects of the request-response cycle. This mechanism consists of actions to manipulate incoming requests or outgoing responses and tailor them to your application’s needs.</p>
<p>Middleware applied to Next.js allows users to shape and control the behavior of their web applications at a granular level without the extra steps, that’s it.</p>
<blockquote>
<p>Middleware’s job is to intercept and manipulate HTTP requests and responses as they pass through the application.</p>
</blockquote>
<p>Now that we understand the fundamental concept, let’s explore the use cases I mentioned. We’ll use both Next.js 13 and Javascript.</p>
<h4>Routing:</h4>
<p>Routing control enables redirecting requests to different URLs handling on, or enforcing URL patterns. This is especially useful when managing complex routing scenarios in your application.</p>
<pre><code>// Next.js
// Redirect requests from the old URL to the new one
export function redirectMiddleware(request: NextRequest) {
  return NextResponse.redirect(&amp;#x27;/new-url&amp;#x27;);
}
</code></pre>
<pre><code>// Javascript
function redirectMiddleware(request) {
  // Redirect to the new URL
  window.location.href = &amp;#x27;/new-url&amp;#x27;;
  // Return an empty response as this code won&amp;#x27;t execute after redirection
  return {
    status: 204, // No content
    body: &amp;#x27;&amp;#x27;,
  };
}
</code></pre>
<h4>Cookie Management:</h4>
<p>Middleware can manage cookies in both incoming requests and outgoing responses. This is essential for tasks like setting user session cookies, reading cookies for authentication, or deleting cookies when a user logs out.</p>
<pre><code>Tyexport function cookieManagementMiddleware(request: NextRequest) {
  const response = NextResponse.next();
  response.cookies.set(&amp;#x27;myCookie&amp;#x27;, &amp;#x27;123&amp;#x27;);
  return response;
}
</code></pre>
<pre><code>function cookieManagementMiddleware(request) {
  const response = {
    status: 200,
    cookies: {
      myCookie: &amp;#x27;123&amp;#x27;,
    },
  };
  return response;
}
</code></pre>
<h4>Authentication:</h4>
<p>Middleware can check whether a user is authenticated before granting access to specific routes or resources.</p>
<p>In the example below, when users attempt to access a protected route, a Middleware function verifies their identity by checking for authentication via session cookies. If the user is not authenticated, they are redirected to a login page or denied access.</p>
<pre><code>// Using Next.js
export function authenticationMiddleware(request: NextRequest) {
  if (!request.headers.cookie?.includes(&amp;#x27;authenticated=true&amp;#x27;)) {
    // Redirect to the login page
    return NextResponse.redirect(&amp;#x27;/login&amp;#x27;);
  }
  return NextResponse.next();
}
</code></pre>
<pre><code>// Using Javascript
function authenticationMiddleware(request) {
  if (!(request.headers.cookie &amp;&amp; request.headers.cookie.includes(&amp;#x27;authenticated=true&amp;#x27;))) {
    // Redirect to the login page
    window.location.href = &amp;#x27;/login&amp;#x27;;
    // Return an empty response as this code won&amp;#x27;t execute after redirection
    return {
      status: 204, // No content
      body: &amp;#x27;&amp;#x27;,
    };
  }
  // Continue to the next middleware or route handler
  return {
    status: 200,
  };
}
</code></pre>
<h4>Logging:</h4>
<p>Detailed logging of incoming requests, including the request method, URL, headers, and timestamp information. These logs are invaluable for diagnosing issues, tracking user activity, and analyzing performance.</p>
<pre><code>export function loggingMiddleware(request: NextRequest) {
  console.log(`Received ${request.method} request to ${request.url} at ${new Date()}`);
  retuTyern NextResponse.next();
}
</code></pre>
<pre><code>function loggingMiddleware(request) {
  console.log(`Received ${request.method} request to ${request.url} at ${new Date()}`);
  return {
    status: 200, // Continue to the next middleware or route handler
  };
}
</code></pre>
<h4>Response Customization:</h4>
<p>Customized response headers, status codes, or the response content based on specific conditions. For instance, you might set custom headers to provide additional information to the client or adjust the response content dynamically.</p>
<pre><code>export function customHeadersMiddleware(request: NextRequest) {
  const response = NextResponse.next();
  response.headers.set(&amp;#x27;X-Custom-Header&amp;#x27;, &amp;#x27;Hello, Middleware!&amp;#x27;);
  response.cookies.set(&amp;#x27;myCookie&amp;#x27;, &amp;#x27;123&amp;#x27;);
  return response;
}
</code></pre>
<pre><code>function customHeadersMiddleware(request) {
  const response = {
    status: 200,
    headers: {
      &amp;#x27;X-Custom-Header&amp;#x27;: &amp;#x27;Hello, Middleware!&amp;#x27;,
    },
    cookies: {
      myCookie: &amp;#x27;123&amp;#x27;,
    },
  };
  return response;
}
</code></pre>
<p>Now that we understand what Middleware is and why it’s useful, let’s start using it in Next.js.</p>
<hr>
<h3>2. Middleware in Next.js</h3>
<h4>The Middleware File</h4>
<p>In Next.js, Middleware is defined in a file typically named <code>middleware.ts</code> (or <code>.js</code>) placed in the root of your project. This file is where you&#39;ll define your Middleware functions. Here&#39;s a basic example function:</p>
<pre><code>// middleware.ts
import { NextResponse } from &amp;#x27;next/server&amp;#x27;;
import type { NextRequest } from &amp;#x27;next/server&amp;#x27;;

export function myMiddleware(request: NextRequest) {
  // Your Middleware logic here
  return NextResponse.next(); // Pass control to the next Middleware or route handler
}
</code></pre>
<h4>NextResponse API</h4>
<p>NextResponse is an API in Next.js that allows you to work with responses in Middleware. It provides methods for redirecting requests, rewriting responses, setting headers, cookies, etc.</p>
<pre><code>import { NextResponse } from &amp;#x27;next/server&amp;#x27;;
import type { NextRequest } from &amp;#x27;next/server&amp;#x27;;

export function myMiddleware(request: NextRequest) {
  // Redirect the request to a different URL
  return NextResponse.redirect(&amp;#x27;/new-url&amp;#x27;);
  // Rewrite the response to display content from a different URL
  return NextResponse.rewrite(&amp;#x27;/new-content&amp;#x27;);
  // Set response headers and cookies
  const response = NextResponse.next();
  response.headers.set(&amp;#x27;X-Custom-Header&amp;#x27;, &amp;#x27;Hello, Middleware!&amp;#x27;);
  response.cookies.set(&amp;#x27;myCookie&amp;#x27;, &amp;#x27;123&amp;#x27;);
  return response;
}
</code></pre>
<h4>Matching Paths</h4>
<h3>3. Using Middleware in Next.js</h3>
<p>Middleware functions in Next.js have access to both the incoming request and the response. You can modify these objects to tailor the behavior of your application.</p>
<pre><code>import { NextResponse } from &amp;#x27;next/server&amp;#x27;;
import type { NextRequest } from &amp;#x27;next/server&amp;#x27;;

export function authenticationMiddleware(request: NextRequest) {
  // Check if the user is authenticated
  if (!request.headers.cookie?.includes(&amp;#x27;authenticated=true&amp;#x27;)) {
    return NextResponse.redirect(&amp;#x27;/login&amp;#x27;);
  }
  return NextResponse.next(); // Continue to the next Middleware or route handler
}
</code></pre>
<h4>Setting Headers and Cookies</h4>
<p>Middleware can manipulate headers and cookies in both incoming requests and outgoing responses. This is useful for tasks like customizing the response or managing user sessions.</p>
<pre><code>import { NextResponse } from &amp;#x27;next/server&amp;#x27;;
import type { NextRequest } from &amp;#x27;next/server&amp;#x27;;

export function customHeadersMiddleware(request: NextRequest) {
  const response = NextResponse.next();
  response.headers.set(&amp;#x27;X-Custom-Header&amp;#x27;, &amp;#x27;Hello, Middleware!&amp;#x27;);
  response.cookies.set(&amp;#x27;myCookie&amp;#x27;, &amp;#x27;123&amp;#x27;);
  return response;
}
</code></pre>
<h4>Producing Custom Responses</h4>
<p>Middleware can produce responses directly by returning a Response or NextResponse instance. This allows you to control the response sent to the client based on your custom logic.</p>
<pre><code>import { NextResponse } from &amp;#x27;next/server&amp;#x27;;
import type { NextRequest } from &amp;#x27;next/server&amp;#x27;;

export function customResponseMiddleware(request: NextRequest) {
  if (/* Some condition */) {
    return new Response(&amp;#x27;Custom error message&amp;#x27;, { status: 400 });
  }
  return NextResponse.next();
}
</code></pre>
<p>Now that we’ve covered the basics, let’s explore some advanced techniques for working with Middleware in Next.js.</p>
<hr>
<h3>4. Advanced Middleware Techniques</h3>
<h4>Intercepting API Calls</h4>
<p>One robust use case for Middleware is intercepting API calls. You can use Middleware to modify API request headers, cache responses, or even mock API calls for testing.</p>
<h4>Modifying Request Headers</h4>
<p>You can use Middleware to modify the headers of outgoing API requests. This is often done to add authentication tokens, API keys, or other necessary information to the headers before sending the request.</p>
<pre><code>import { NextResponse } from &amp;#x27;next/server&amp;#x27;;
import type { NextRequest } from &amp;#x27;next/server&amp;#x27;;

export function apiInterceptorMiddleware(request: NextRequest) {
  // Modify the API request headers
  request.headers.set(&amp;#x27;Authorization&amp;#x27;, &amp;#x27;Bearer myAccessToken&amp;#x27;);

  // Cache API responses for improved performance
  // Implement caching logic here

  return NextResponse.next();
}
</code></pre>
<h4>Caching API Responses</h4>
<p>To improve the performance of your application, you can implement caching of API responses within Middleware. This helps reduce the load on external APIs and speeds up subsequent requests for the same data.</p>
<pre><code>import { NextResponse } from &amp;#x27;next/server&amp;#x27;;
import type { NextRequest } from &amp;#x27;next/server&amp;#x27;;

export function apiInterceptorMiddleware(request: NextRequest) {
  // Check if the response is already cached
  const cachedResponse = /* Implement caching logic here */;

  if (cachedResponse) {
    // If cached, return the cached response
    return cachedResponse;
  } else {
    // If not cached, make the API request and cache the response
    const apiResponse = /* Make the API request */;

    // Cache the response for future use
    /* Cache the response */

    return apiResponse;
  }
}
</code></pre>
<h4>Mocking API Calls for Testing</h4>
<p>Middleware can also be used to mock API calls during testing. This ensures that your tests are not dependent on external services, making them more reliable and faster.</p>
<pre><code>import { NextResponse } from &amp;#x27;next/server&amp;#x27;;
import type { NextRequest } from &amp;#x27;next/server&amp;#x27;;

export function apiMockMiddleware(request: NextRequest) {
  if (process.env.NODE_ENV === &amp;#x27;test&amp;#x27;) {
    // In a testing environment, return a mocked response
    return new Response(JSON.stringify({ mockData: true }), {
      status: 200,
      headers: {
        &amp;#x27;Content-Type&amp;#x27;: &amp;#x27;application/json&amp;#x27;,
      },
    });
  } else {
    // In other environments, continue to the next Middleware or route handler
    return NextResponse.next();
  }
}
</code></pre>
<p>These advanced techniques illustrate Middleware&#39;s flexibility and power when handling API calls in your Next.js application. Whether you need to secure your API requests, optimize performance with caching, or simplify testing with mock responses, Middleware can be your go-to solution.</p>
<hr>
<h3>5. Middleware Upgrade Guide</h3>
<p>If you have been using Middleware in earlier versions of Next.js and plan to upgrade to version 12.2 or later, you must be aware of changes and improvements made to the Middleware API. These changes might require you to update your existing Middleware code. Refer to the official Next.js documentation for detailed upgrade instructions.</p>
<hr>
<p>This should cover fundamental concepts and advanced techniques to manage your web application’s request and response flow, authentication, logging, response customization, routing control, etc.</p>
<p>You can explore the <a href="https://nextjs.org/docs/app/building-your-application/routing/middleware">official Next.js documentation on Middleware</a>information and official examples.</p>
<p><em>By Zach Shallbetter</em></p>
<p><em>Creative Product &amp; Technology Leader | Building Teams and Human-Centered Solutions | Spokane Washington</em></p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/middleware-in-next-js-a-comprehensive-guide">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>Spokane’s Fiber Future</title>
      <link>https://zachshallbetter.com/writing/spokane-s-fiber-future</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/spokane-s-fiber-future</guid>
      <pubDate>Thu, 28 Sep 2023 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>This is the complete talk I gave to the Spokane City Council on February 26th 2018 regarding the benefits of Municipal Broadband. I ran out…</description>
      <content:encoded><![CDATA[<p><em>This is the complete talk I gave to the Spokane City Council on February 26th 2018 regarding the benefits of Municipal Broadband. I ran out of time, so they didn’t hear it entirely, but I think at around 50% in, you get the gist.</em></p>
<p>First off, as a member of the local technology community, business community, and head of the Inland Northwest Technologists, I want to praise the council for taking the time to consider the possibilities that Municipal Broadband will bring to our city. Spending the energy to research community growth opportunities is the basis of a well-run system and proves our government is responsible and open to new ideas.</p>
<p>Building a workgroup of passionate minds from around our community, it shows the intent to actively seek out information that will determine whether the costs of Municipal Broadband outweigh the benefits, or if the endeavor is even feasible. The best part is that this brain trust costs the taxpayers absolutely nothing.</p>
<p>The Council is researching the opportunity to take control of the fiber network that the taxpayers have already invested in. To enhance, improve, and offer a service that benefits the community financially. We rarely find ourselves in a position to garner a reasonable return on the infrastructure that has been in the ground and above our streets for decades.</p>
<p>Moreover, much like the water department is accountable to the public and does not raise water rates unreasonably, those running our community network would be accountable to the public. If the community offered subsidized connections to those living below the poverty line, they could do that. We could do that more than a few community channels or increase the broadband speed. If it wanted to provide free service to all of the schools, libraries, and government institutions, it could do that, and save assumingly tens of thousands of dollars if not more.</p>
<p>In communities similar to ours, and there are many, the local government or public power utility has a department that provides these services. In others, the network is only open to private service providers who compete for customers on equal terms. Some cities have even used a hybrid approach where the city offers services and non-discriminatory wholesale access to other providers and competes against them.</p>
<p>That’s the point of doing research and creating a working group. To find opportunities that benefit everyone in our community, not just a few massive telecommunications companies, not one side of the political playing field or the other, but the community.</p>
<p>The private sector aims to maximize profit and shareholder value, primarily in the short term. At the same time, the public sector maximizes social benefit and focuses on the long term. They don’t have to advertise or answer to Wall Street.</p>
<p>Understanding these differences in important to understanding why infrastructure has historically been owned or closely regulated by the public sector. Frankly if GM owning the roads; they would find it quite profitable to ban competing car companies or force them to pay more to access the same roads.</p>
<p>But there’s an argument that we often hear; statements like “the government should not compete with the private sector” this thinking ignores the many ways in which we already accept important government services that “compete” with the private sector. Libraries might take customers from bookstores. The Police forces compete with private sector security guards. Or even the Postal Service competes with Fedex and UPS.</p>
<p>This is a discussion we need to have about our infrastructure and our community. Should the private sector control our infrastructure and destiny? Shouldn’t small businesses have the opportunity to try and utilize the lines that we as citizens paid for? Our broadband network is a 21st century infrastructure that will allow this city to move into the economic future with minimal effort.</p>
<p>When Eisenhower decided to push the Interstate system, it was not with the idea that everyone would have to use it. However, business and government functions were greatly improved by this massive infrastructure project. Over time, more and more people recognized its value and shared the understanding that their tax dollars go to improving that system at every level.</p>
<p>Even further, in our underserved communities, those who can’t afford even the most basic service can experience a reasonable service even if they don’t have a physical location or the means to pay the current setup rates and costly prices they have now.</p>
<p>The fact of the matter is that we need more choices and more control. Two service providers in this city monopolize the market. As a community, we own this infrastructure and require a certain level of service. We demand fast, affordable, internet that’s available to everyone at every place in their lives.</p>
<p>And to the naysayers, this isn’t experimental. [Data exits]. Many cities that have successfully implemented their internet service, either publicly or through public-private partnerships, have seen 10x times the speed we get in Spokane now. Because of this, the growth of industries excluded in our region will boom. Data Centers, call centers, manufacturing, startups, and every other level of business that utilizes technology will grow. We will receive offerings from businesses that want to move into places like ours that offer an incredible lifestyle and tech infrastructure unlike anything else in our state.</p>
<p>It’s about as aggressive an economic motivator as you can get when you count the tax revenue, entry-level jobs, construction, and reduced unemployment that comes with it.</p>
<p>This is an opportunity to shape our future through the democratic process. To form a team to discuss and think about the ramifications and impact of taking over our infrastructure. To grow and express our independence and power over our destiny.</p>
<p>Without question, it’s a win-win for everyone.</p>
<p>Thank you</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/spokane-s-fiber-future">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>Unit Test Next.js API Routes with TypeScript.</title>
      <link>https://zachshallbetter.com/writing/unit-test-next-js-api-routes-with-typescript</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/unit-test-next-js-api-routes-with-typescript</guid>
      <pubDate>Thu, 17 Aug 2023 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>Elevate your code with smart test pattern.</description>
      <content:encoded><![CDATA[<p>Testing API routes sucks, especially when using TypeScript. This article covers how to unit test Next.js API routes with TypeScript using Jest and React Testing Libraries.</p>
<blockquote>
<p>This writeup is for personal reference — consume at your discretion.</p>
</blockquote>
<h3>Why Test API Routes?</h3>
<p>Testing API routes is important for several reasons. First, it helps you ensure that your routes work as expected and handle different scenarios gracefully. For example, you can test that your routes return the correct data, handle errors properly, and respond to different types of requests (e.g., GET, POST, PUT, DELETE).</p>
<p>Second, testing API routes can help you prevent bugs, errors, security issues, and performance problems in your application. By writing tests for your routes, you can catch issues early on and fix them before they become bigger problems.</p>
<p>Third, testing API routes can help you improve the quality of your code and make it more maintainable. By writing tests for your routes, you can document their behavior and make it easier for other developers to understand how they work.</p>
<h3>Tools and Libraries</h3>
<p>To test Next.js API routes with TypeScript, we will use several tools and libraries:</p>
<ul>
<li><p>Jest: a JavaScript testing framework that provides a complete testing solution for JavaScript applications.</p>
</li>
<li><p>React Testing Library: a library for testing React components that provides a set of helper functions to interact with the DOM.</p>
</li>
<li><p>node-mocks-http: a library that provides mock objects for Node.js HTTP requests and responses.</p>
</li>
<li><p>dotenv: a library that loads environment variables from a <code>.env</code> file into <code>process.env</code>.</p>
</li>
<li><p>@types/node: a package that provides TypeScript definitions for Node.js built-in modules.</p>
</li>
</ul>
<p>Run the following command in your terminal to install:</p>
<pre><code>npm install --save-dev jest @testing-library/react node-mocks-http dotenv @types/node[^3^][3]
</code></pre>
<p>After installing these tools and libraries, you need to configure Jest to work with Next.js and TypeScript. You can do this by creating a <code>jest.config.js</code> file in the root of your project with the following content:</p>
<pre><code>module.exports = {
  testEnvironment: &amp;#x27;jsdom&amp;#x27;,
  transform: {
    &amp;#x27;^.+\\.(js|jsx|ts|tsx)$&amp;#x27;: &amp;#x27;&lt;rootDir&gt;/node_modules/babel-jest&amp;#x27;,
  },
  moduleNameMapper: {
    &amp;#x27;^.+\\.(css|less|scss)$&amp;#x27;: &amp;#x27;identity-obj-proxy&amp;#x27;,
  },
}
</code></pre>
<p>This configuration tells Jest to use jsdom as the test environment, use Babel to transform JavaScript and TypeScript files, and mock CSS modules with an identity object proxy.</p>
<h3>Testing GET Requests</h3>
<p>To test GET requests to a Next.js API route using the App Router, you must create a mock request object, a mock response object, and a handler function representing your route. You can use node-mocks-http to create the mock objects and pass them to your handler function.</p>
<p>Here is an example of how to test a GET request to an API route that returns a list of users:</p>
<pre><code>// app/api/users.page.ts
import type { NextRequest } from &amp;#x27;next/server&amp;#x27;
import type { NextResponse } from &amp;#x27;next/server&amp;#x27;

type User = {
  id: number
  name: string
}

const users: User[] = [
  { id: 1, name: &amp;#x27;Alice&amp;#x27; },
  { id: 2, name: &amp;#x27;Bob&amp;#x27; },
]

export default function handler(req: NextRequest) {
  return NextResponse.json(users)
}

// app/api/users.test.ts
import { createMocks } from &amp;#x27;node-mocks-http&amp;#x27;
import handler from &amp;#x27;./users.page&amp;#x27;

describe(&amp;#x27;/api/users&amp;#x27;, () =&gt; {
  test(&amp;#x27;returns a list of users&amp;#x27;, async () =&gt; {
    const { req, res } = createMocks({
      method: &amp;#x27;GET&amp;#x27;,
    })

    const response = await handler(req)

    expect(response.status).toBe(200)
    expect(await response.json()).toEqual([
      { id: 1, name: &amp;#x27;Alice&amp;#x27; },
      { id: 2, name: &amp;#x27;Bob&amp;#x27; },
    ])
  })
})
</code></pre>
<p>In this example, we use the <code>createMocks</code> function from node-mocks-http to create a mock request object with the <code>method</code> property set to <code>&#39;GET&#39;</code> and a mock response object. We pass the mock request object to our <code>handler</code> function and wait for it to return a response.</p>
<p>After calling our <code>handler</code> function, we use Jest’s <code>expect</code> function and its matchers (e.g., <code>toBe</code>, <code>toEqual</code>) to assert the expected behavior of our route. In this case, we expect our route to return a <code>200</code> status code and a list of users.</p>
<h3>Testing POST Requests</h3>
<p>To test POST requests to a Next.js API route using the App Router, you need to create a mock request object with the <code>method</code> property set to <code>&#39;POST&#39;</code> and the <code>body</code> property set to the data you want to send in the request. You also need to create a handler function that represents your route.</p>
<p>Here is an example of how to test a POST request to an API route that creates a new user:</p>
<pre><code>// app/api/users.page.ts
import type { NextRequest } from &amp;#x27;next/server&amp;#x27;
import type { NextResponse } from &amp;#x27;next/server&amp;#x27;

type User = {
  id: number
  name: string
}

let users: User[] = [
  { id: 1, name: &amp;#x27;Alice&amp;#x27; },
  { id: 2, name: &amp;#x27;Bob&amp;#x27; },
]

export default function handler(req: NextRequest) {
  if (req.method === &amp;#x27;POST&amp;#x27;) {
    const newUser = req.body as User
    newUser.id = users.length + 1
    users.push(newUser)
    return NextResponse.created(users)
  } else {
    return NextResponse.json(users)
  }
}

// app/api/users.test.ts
import { createMocks } from &amp;#x27;node-mocks-http&amp;#x27;
import handler from &amp;#x27;./users.page&amp;#x27;

describe(&amp;#x27;/api/users&amp;#x27;, () =&gt; {
  test(&amp;#x27;creates a new user&amp;#x27;, async () =&gt; {
    const { req, res } = createMocks({
      method: &amp;#x27;POST&amp;#x27;,
      body: { name: &amp;#x27;Charlie&amp;#x27; },
    })

    const response = await handler(req)

    expect(response.status).toBe(201)
    expect(await response.json()).toEqual([
      { id: 1, name: &amp;#x27;Alice&amp;#x27; },
      { id: 2, name: &amp;#x27;Bob&amp;#x27; },
      { id: 3, name: &amp;#x27;Charlie&amp;#x27; },
    ])
  })
})
</code></pre>
<p>In this example, we use the <code>createMocks</code> function from node-mocks-http to create a mock request object with the <code>method</code> property set to <code>&#39;POST&#39;</code> and the <code>body</code> property set to an object with the <code>name</code> property set to <code>&#39;Charlie&#39;</code>. We pass this object to our <code>handler</code> function and wait for it to return a response.</p>
<p>After calling our <code>handler</code> function, we use Jest’s <code>expect</code> function and its matchers (e.g., <code>toBe</code>, <code>toEqual</code>) to assert the expected behavior of our route. In this case, we expect our route to return a <code>201</code> status code and a list of users, including the new user.</p>
<h3>Testing Other Scenarios</h3>
<p>In addition to testing GET and POST requests, you can also test other scenarios and inputs for your API routes using the App Router. For example, you can test error handling, validation, authentication, authorization, headers, cookies, query parameters, body parameters, etc.</p>
<p>Here is an example of how to test error handling in an API route that returns a user by ID:</p>
<pre><code>// app/api/users/[id].page.ts
import type { NextRequest } from &amp;#x27;next/server&amp;#x27;
import type { NextResponse } from &amp;#x27;next/server&amp;#x27;

type User = {
  id: number
  name: string
}

const users: User[] = [
  { id: 1, name: &amp;#x27;Alice&amp;#x27; },
  { id: 2, name: &amp;#x27;Bob&amp;#x27; },
]

export default function handler(req: NextRequest) {
  const id = Number(req.query.id)
  const user = users.find((user) =&gt; user.id === id)
  if (user) {
    return NextResponse.json(user)
  } else {
    return NextResponse.notFound({ message: &amp;#x27;User not found&amp;#x27; })
  }
}

// app/api/users/[id].test.ts
import { createMocks } from &amp;#x27;node-mocks-http&amp;#x27;
import handler from &amp;#x27;./[id].page&amp;#x27;

describe(&amp;#x27;/api/users/[id]&amp;#x27;, () =&gt; {
  test(&amp;#x27;returns a user by ID&amp;#x27;, async () =&gt; {
    const { req, res } = createMocks({
      method: &amp;#x27;GET&amp;#x27;,
      query: { id: &amp;#x27;1&amp;#x27; },
    })
    const response = await handler(req)
    expect(response.status).toBe(200)
    expect(await response.json()).toEqual({ id: 1, name: &amp;#x27;Alice&amp;#x27; })
  })

  test(&amp;#x27;returns an error if the user is not found&amp;#x27;, async () =&gt; {
    const { req, res } = createMocks({
      method: &amp;#x27;GET&amp;#x27;,
      query: { id: &amp;#x27;3&amp;#x27; },
    })
    const response = await handler(req)
    expect(response.status).toBe(404)
    expect(await response.json()).toEqual({ message: &amp;#x27;User not found&amp;#x27; })
  })
})
</code></pre>
<p>In this example, we use the <code>createMocks</code> function from node-mocks-http to create two sets of mock objects for our tests. The first set has a mock request object with the <code>method</code> property set to <code>&#39;GET&#39;</code> and the <code>query</code> property set to an object with the <code>id</code> property set to <code>&#39;1&#39;</code>. The second set has a mock request object with the <code>method</code> property set to <code>&#39;GET&#39;</code> and the <code>query</code>property set to an object with the <code>id</code> property set to <code>&#39;3&#39;</code>. We pass these objects and their corresponding mock response objects to our <code>handler</code> function and wait for it to finish.</p>
<p>After calling our <code>handler</code> function, we use Jest’s <code>expect</code> function and its matchers (e.g., <code>toBe</code>, <code>toEqual</code>) to assert the expected behavior of our route1. In the first test, we expect our route to return a <code>200</code> status code and a user object with the <code>id</code> property set to <code>1</code>. In the second test, we expect our route to return a <code>404</code> status code and an error message.</p>
<h3>Conclusion</h3>
<p>This article shows you how to unit test Next.js API routes with TypeScript using Jest and React Testing Library. We have covered the tools and libraries you need and examples of testing different types of requests and scenarios.</p>
<p>By following these steps, you can write tests for your API routes and ensure they work as expected. You can also improve the quality of your code, prevent bugs and errors, and make your application more secure and performant.</p>
<p><em>By Zach Shallbetter,</em></p>
<p><em>Creative Product &amp; Technology Leader | Building Teams and Human-Centered Solutions in Spokane Washington.</em></p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/unit-test-next-js-api-routes-with-typescript">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>Testing Routes in Next.js 13</title>
      <link>https://zachshallbetter.com/writing/testing-routes-in-next-js-13</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/testing-routes-in-next-js-13</guid>
      <pubDate>Thu, 17 Aug 2023 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>Note: 8/28— I’ve refreshed the content after some experimentation and the release of 13.5.</description>
      <content:encoded><![CDATA[<blockquote>
<p>Note: 8/28— I’ve refreshed the content after some experimentation and the release of 13.5.</p>
</blockquote>
<ul>
<li><p>Built a gist that contains examples.</p>
</li>
<li><p>Leans less into node-mocks.</p>
</li>
<li><p>Explains routing, (because it feels weird without it).</p>
</li>
</ul>
<p><em>Complete examples can be found in the associated Gist:</em><a href="https://gist.github.com/zachshallbetter/3301419b75958218d1b5853147a16263">https://gist.github.com/zachshallbetter</a><em>.</em></p>
<p>This guide will explore various ways to test routes in Next.js 13. It includes the necessary information and tools to confirm and execute the correct route behavior.</p>
<h3>What is Routing exactly?</h3>
<p>Routing, in the context of web development, refers to the process of determining how an application responds to a specific URL or URI (Uniform Resource Identifier) request. It involves defining rules or patterns that map these URLs to specific actions or content within the web application.</p>
<p>Routing is a fundamental concept in web development, and it serves several purposes:</p>
<ul>
<li><p><strong>Navigation</strong>: Routing allows users to navigate between different pages or views within a web application. For example, clicking on a link or typing a URL in the browser’s address bar triggers loading a corresponding page.</p>
</li>
<li><p><strong>Content Delivery</strong>: It ensures that the appropriate content or data is delivered in response to a specific URL request. This can involve rendering HTML templates, serving JSON data, or performing other actions based on the URL.</p>
</li>
<li><p><strong>State Management</strong>: Routing often plays a role in managing the state of a web application. Different URLs can represent different states or views of the application, and routing helps maintain and switch between these states.</p>
</li>
<li><p><strong>Authentication and Authorization</strong>: Routing can be used to protect certain routes or pages, ensuring that only authenticated and authorized users can access them. It’s a critical component of web application security.</p>
</li>
<li><p><strong>SEO (Search Engine Optimization)</strong>: Proper routing is essential for SEO. Search engines use the URL structure of a website to index its content, so well-structured and semantic URLs can improve a website’s search engine ranking.</p>
</li>
</ul>
<p>In modern web development, routing is typically handled by frameworks and libraries, making it easier for developers to define and manage routes. Popular web frameworks like Next.js, React Router, Angular Router, and Vue Router provide tools and APIs for creating and handling routes in web applications.</p>
<p>Testing ensures that your routes work as expected and handle different scenarios gracefully; depending on the type of route and the level of testing you want to perform, your mileage may vary.</p>
<h3>Testing Tools</h3>
<p>Jest and <code>**node-mocks-http**</code> are two essential tools used in testing routes and server-side logic, particularly in Next.js applications. Let&#39;s delve into what each of these tools is and how they contribute to testing:</p>
<h4><strong>Jest:</strong></h4>
<p>Jest is a popular JavaScript testing framework developed by Facebook. It is widely used for testing JavaScript applications, including both client-side and server-side code. Jest is known for its simplicity, speed, and powerful features.</p>
<p><strong>Key Features and Capabilities:</strong></p>
<ul>
<li><p><strong>Test Runner:</strong> Jest provides a test runner that executes test suites and individual test cases.</p>
</li>
<li><p><strong>Assertion Library:</strong> It includes an assertion library with functions like <code>**expect**</code> for making assertions and checking expected outcomes.</p>
</li>
<li><p><strong>Mocking:</strong> Jest offers built-in mocking capabilities for functions, modules, and timers, making it easy to isolate and control the behavior of various parts of your code.</p>
</li>
<li><p><strong>Asynchronous Testing:</strong> Jest simplifies testing asynchronous code with features like async/await support and the <code>**done**</code> callback.</p>
</li>
<li><p><strong>Snapshot Testing:</strong> Jest allows you to create and compare snapshots of rendered components, making it useful for testing UI components.</p>
</li>
<li><p><strong>Parallel Test Execution:</strong> It can run tests in parallel for improved performance.</p>
</li>
<li><p><strong>Code Coverage:</strong> Jest can generate code coverage reports to identify untested code.</p>
</li>
</ul>
<p><strong>Use in Testing Routes:</strong></p>
<ul>
<li><p>In the context of testing routes in Next.js, Jest is used as the testing framework for writing test cases.</p>
</li>
<li><p>Developers use Jest’s <code>**expect**</code> and other assertion functions to make assertions about the behavior of routes and their components.</p>
</li>
<li><p>Jest is particularly useful for testing asynchronous operations, such as data fetching using functions like <code>**getServerSideProps**</code> and <code>**getStaticProps**</code>.</p>
</li>
</ul>
<h4><strong>node-mocks-http:</strong></h4>
<p><code>**node-mocks-http**</code> is a library for Node.js that provides mock objects for simulating HTTP requests and responses. It is especially valuable for testing server-side logic in Node.js applications, including Express.js and in our case, Next.js.</p>
<p><strong>Key Features and Capabilities:</strong></p>
<ul>
<li><p><strong>Customization:</strong> You can customize the properties and methods of these mock objects to simulate various scenarios and test edge cases.</p>
</li>
<li><p><strong>Middleware Testing:</strong> It is suitable for testing middleware functions that process HTTP requests and responses.</p>
</li>
<li><p><strong>Integration with Testing Frameworks:</strong> <code>**node-mocks-http**</code> can be seamlessly integrated with testing frameworks like Jest to test server-side code.</p>
</li>
</ul>
<p><strong>Use in Testing Routes:</strong></p>
<ul>
<li><p>When testing routes in Next.js, developers often use <code>**node-mocks-http**</code> to create mock request and response objects.</p>
</li>
<li><p>These mock objects are then passed to route functions, allowing developers to simulate HTTP requests and observe the responses.</p>
</li>
<li><p>By customizing the mock objects, developers can simulate different scenarios, test error handling, and validate route behavior.</p>
</li>
</ul>
<h3>Testing with Jest and node-mocks-http</h3>
<p><a href="https://jestjs.io/">Jest</a>, when combined with node-mocks-http, provides a powerful and flexible way to test route behavior. With this approach, you can:</p>
<ul>
<li><p>Create mock functions that capture calls, arguments, return values, and contexts.</p>
</li>
<li><p>Mock modules and their exports, including ES and CommonJS modules.</p>
</li>
<li><p>Mock constructors and instances of classes.</p>
</li>
<li><p>Configure mock implementations and return values for different scenarios.</p>
</li>
<li><p>Restore the original behavior of mocked functions and modules.</p>
</li>
</ul>
<h3>How to test Routes</h3>
<p>There are two primary approaches to testing routes:</p>
<ul>
<li><p><strong>Using the Development Server and Browser:</strong> This approach involves utilizing the built-in development server and a web browser. By running <code>npm run dev</code> in your terminal and navigating to the route&#39;s URL, you can visually inspect how the route renders in the browser and check for any errors or warnings in the console.</p>
</li>
<li><p><strong>Leveraging Testing Frameworks and Libraries:</strong> Using frameworks and libraries to automate route testing for repeatability, we implement unit or integration tests without needing a browser. We’ll focus on this approach in detail.</p>
</li>
</ul>
<p>Testing a route in a web application, such as a Next.js application, involves creating a controlled environment to send requests to the route and verify the responses.</p>
<p>Here’s a step-by-step explanation of how testing a route typically works:</p>
<ul>
<li><p><strong>Setup Testing Environment:</strong></p>
</li>
<li><p>Import Testing Libraries: First, import the necessary testing libraries and dependencies. In a Next.js application, you’ll commonly use testing frameworks like Jest and libraries like <code>**node-mocks-http**</code> for creating mock HTTP request and response objects.</p>
</li>
<li><p>Import the Route: Import the specific route or endpoint you want to test. This route should be part of your application’s codebase.</p>
</li>
</ul>
<p><strong>2. Create Mock Request and Response Objects:</strong></p>
<ul>
<li><p>You create mock request and response objects using the node-mocks-http library or a similar tool. These objects mimic the behavior of actual HTTP requests and responses but in a controlled and predictable way.</p>
</li>
<li><p>Customize Mock Objects: You can customize these mock objects to simulate various scenarios. For example, you can set the HTTP method, and provide request parameters, headers, and more depending on the route’s requirements.</p>
</li>
</ul>
<p><strong>3. Invoke the Route Function:</strong></p>
<ul>
<li>Call the route function you imported, passing in the mock request and response objects as arguments. This simulates the route being invoked as if an actual HTTP request was triggered.</li>
</ul>
<p><strong>4. Assertions and Expectations:</strong></p>
<ul>
<li><p>After invoking the route, you use testing assertions provided by your testing framework (e.g., Jest) to make assertions about the behavior and response of the route.</p>
</li>
<li><p>You can check things like:</p>
</li>
<li><p>The HTTP status code returned by the route (e.g., expecting a 200 OK status for a successful request).</p>
</li>
<li><p>The content of the response, such as JSON data or HTML markup.</p>
</li>
<li><p>The presence of specific headers in the response.</p>
</li>
<li><p>The behavior of the route in different scenarios (e.g., error handling).</p>
</li>
</ul>
<p><strong>Run and Review Results:</strong></p>
<ul>
<li><p>Execute your test suite using your chosen framework (e.g., running <code>**npm test**</code> for Jest).</p>
</li>
<li><p>The testing framework will report the results of the tests. You can see which tests passed and which failed.</p>
</li>
</ul>
<p><strong>Clean Up (Optional):</strong></p>
<ul>
<li>Depending on your testing framework and setup, you might need to perform cleanup tasks after each test case, such as resetting the state or clearing any temporary data.</li>
</ul>
<p><strong>Iterate and Repeat for Different Scenarios</strong></p>
<ul>
<li><p>If tests fail, review the failure messages to understand what went wrong. Debug and make necessary adjustments to your route or test cases.</p>
</li>
<li><p>You can create multiple test cases to cover various scenarios for the route. For instance, you might test success scenarios, error handling, authentication, and edge cases.</p>
</li>
</ul>
<h3>A Practical Example</h3>
<h3>A Practical Example</h3>
<p>Let’s walk through a practical testing example that demonstrates how to set up a test, create mock request and response objects, and assert the expected behavior of a route.</p>
<pre><code>// Import the route file and the library
import hello from &amp;#x27;./api/hello&amp;#x27;
import { createMocks } from &amp;#x27;node-mocks-http&amp;#x27;

// Write a test using Jest
test(&amp;#x27;should return a greeting message&amp;#x27;, async () =&gt; {
  // Create mock request and response objects
  const { req, res } = createMocks({
    method: &amp;#x27;GET&amp;#x27;,
  })

  // Call the route function with the mock objects
  await hello(req, res)

  // Assert the expected behavior
  expect(res._getStatusCode()).toBe(200)
  expect(res._getData()).toEqual({ message: &amp;#x27;Hello Next.js&amp;#x27; })
})
</code></pre>
<h3>Exploring Alternatives</h3>
<p>While Jest and node-mocks-http are powerful tools for route testing in Next.js, there are alternative libraries and tools available. You can choose the one that best suits your specific needs and preferences. Some alternatives include Sinon.js, Rewire, and Proxyquire, each with its own strengths and considerations.</p>
<p>In the associated Gist, you’ll find complete code examples for testing routes using Jest and node-mocks-http. These examples will help you get started with route testing in Next.js and ensure the reliability of your application’s routes.</p>
<p>Remember that effective route testing is crucial for delivering a robust and error-free web application. By following the methods and examples provided in this guide, you’ll be well-equipped to test your Next.js routes effectively.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/testing-routes-in-next-js-13">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>GitHub Profile Tuning: A Senior Developer’s Guide to Job Seeking</title>
      <link>https://zachshallbetter.com/writing/github-profile-tuning-a-senior-developer-s-guide-to-job-seeking</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/github-profile-tuning-a-senior-developer-s-guide-to-job-seeking</guid>
      <pubDate>Thu, 17 Aug 2023 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description></description>
      <content:encoded><![CDATA[<p>Creative Product &amp; Technology Leader | Building Teams and Human-Centered Solutions</p>
<p>The vast and ever-expanding digital metropolis of software development is built line-by-line. Beyond the code itself, your GitHub profile stands as a beacon of your relationship with that code.</p>
<p>Amidst the bustling crowds of code crafters and digital denizens, a well-optimized GitHub profile can be the colossal kaiju that sets you apart in the hunt for opportunities.</p>
<p>My own GitHub profile (which you can explore here: <a href="https://github.com/zachshallbetter">Zach Shallbetter’s GitHub</a>) is a testament to this approach. With the same intensity as the kaiju cat’s gaze, I’ll share the strategies that help my GitHub presence command attention.</p>
<h3>High-Level Tips for Optimizing Your GitHub Profile</h3>
<h4>1. Choose a Professional Profile Picture</h4>
<p>Your profile picture is your virtual handshake. It should be professional, welcoming, and aligned with the industry standards. Think of it as a part of your personal brand that sets the tone for your profile.</p>
<h4>2. Craft a Compelling Bio</h4>
<p>Your bio is more than just a summary; it’s your elevator pitch. It should briefly showcase your skills, passions, and what makes you unique as a developer. Be concise, clear, and captivating.</p>
<h4>3. Showcase Your Best Work</h4>
<p>Make sure your most impressive and relevant projects are front and center. These projects should reflect your expertise and the work you want to in the future.</p>
<h4>4. Maintain Clean Code</h4>
<p>Your repositories are a direct reflection of your coding standards. Keep your code well-organized, properly commented, and follow best practices. This demonstrates your professionalism and attention to detail.</p>
<h4>5. Contribute to Open-Source Projects</h4>
<p>Active contributions to open-source projects showcase your collaborative skills and commitment to the development community. This can be a significant differentiator for potential employers.</p>
<h4>6. Keep Your Profile Current</h4>
<p>Your GitHub profile should be a living portfolio. Regularly update it with new skills, projects, and contributions to keep it reflective of your current abilities and aspirations.</p>
<h3>Advanced Tips for the Detail-Oriented</h3>
<h4>Code Optimization: Performance Matters</h4>
<p>Good code is more than just working code. It’s about efficiency and optimization. Demonstrate your proficiency in writing high-performance code. This could be through optimized algorithms, effective use of data structures, or employing best coding practices.</p>
<h4>Showcase Your Skills: Utilize Projects</h4>
<p>Projects are the backbone of your GitHub profile. Use them to demonstrate not just your coding skills but also your problem-solving abilities, creativity, and capacity to work on complex tasks.</p>
<h4>Personal Branding: Tell Your Story Through GitHub</h4>
<p>Use your GitHub account as a storytelling tool. Share your journey, your evolving skills, and the unique experiences that make you stand out as a developer. Your profile should be a tapestry of your professional journey.</p>
<h4>Embrace Open-Source: Collaborate and Contribute</h4>
<p>Engaging with the open-source community is a powerful way to demonstrate your skills. It shows your ability to collaborate on projects, interact with other developers, and contribute to the larger tech community.</p>
<h4>Continuous Learning: Stay Current with Technology</h4>
<p>Showcase your ongoing learning process. Whether it’s experimenting with new technologies or refining existing skills, your GitHub profile should reflect a trajectory of growth and adaptability.</p>
<h4>Quality Over Quantity: Be Strategic</h4>
<p>Curate your GitHub profile with a focus on quality. Select projects that best represent your skills and what you bring to the table as a developer. It’s about showcasing your strengths in the best light.</p>
<h4>Clean Commit History: Narrate Your Process</h4>
<p>A clean and organized commit history is a sign of a professional developer. Use meaningful commit messages that explain the “why” behind your changes, making it easier for others (and yourself) to follow your development process.</p>
<h4>Authenticity and Originality: Build Trust</h4>
<p>Your work should be a reflection of your authentic self. Avoid copying others’ work and strive for original contributions. Authenticity in your work builds trust and showcases your integrity as a developer.</p>
<h4>Real-World Experience: Show Teamwork</h4>
<p>Highlight projects where you’ve collaborated with others, whether it’s in a professional setting, open-source contributions, or team projects. This demonstrates your ability to work effectively in team environments.</p>
<h4>Commitment to Excellence: CI, Testing, Documentation</h4>
<p>Show your dedication to quality and best practices through consistent use of Continuous Integration (CI) pipelines, thorough testing, and comprehensive documentation. This illustrates a commitment to producing high-quality, reliable code.</p>
<h4>Profile Presentation: Craft Your Image</h4>
<p>Pay attention to the aesthetics and organization of your profile. Use README files effectively, maintain a consistent theme across your repositories, and ensure all links and images are working correctly. A well-presented profile speaks volumes.</p>
<h4>Networking and Community: Build Connections</h4>
<p>Engage with the GitHub community. Star, fork, and contribute to projects that interest you. Networking can open doors to new opportunities and collaborations.</p>
<h4>Structuring Your GitHub Account: Executive Tips</h4>
<p>Strategically structure your profile to highlight your best work. Pin your most impressive repositories, keep your profile updated, and use READMEs to guide visitors through your portfolio.</p>
<h3>Conclusion</h3>
<p>Github’s a platform that allows you to showcase not just your coding skills, but your journey as a developer, your commitment to growth, and your engagement with the broader tech community. By focusing on quality, authenticity, collaboration, and professionalism, you can create a profile that resonates with employers and peers alike. Remember, everything online is expands the story about you.</p>
<p><em>By Zach Shallbetter</em></p>
<p><em>Creative Product &amp; Technology Leader | Building Teams and Human-Centered Solutions</em></p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/github-profile-tuning-a-senior-developer-s-guide-to-job-seeking">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>CIPM — The Cognitive Information Processing Model</title>
      <link>https://zachshallbetter.com/writing/cipm-the-cognitive-information-processing-model</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/cipm-the-cognitive-information-processing-model</guid>
      <pubDate>Tue, 25 Jul 2023 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>Navigating the Mind’s Labyrinth</description>
      <content:encoded><![CDATA[<h3>Navigating the Mind’s Labyrinth</h3>
<p>The human mind can be likened to a labyrinth in its staggering complexity. Each winding pathway and obscure corner of this vast maze represents the myriad neural patterns and connections forged from birth and throughout life. It’s a place of wonder, a testament to the multifaceted nature of our thoughts, emotions, memories, and dreams. Like any intricate maze, its vastness can be overwhelming, its passages enigmatic, and its dead-ends confounding.</p>
<p>Imagine wandering this neurological labyrinth without a guide, feeling lost amid the ever-tangling web of neurons, synaptic responses, and electrical impulses. The countless turns and twists represent our shifting emotions, evolving perceptions, and burgeoning memories. But what if there was a map, an intricate blueprint that could help us navigate through this mesmerizing, intricate terrain?</p>
<p>Enter the Cognitive Information Processing Model (CIPM). Much like a cartographer’s meticulously detailed map, CIPM lays out the routes of cognition, shining a torchlight on the shadowy alcoves of our subconscious and offering a clear trail through our conscious thoughts. It breaks down the vast expanse of the labyrinth into discernible sections, each corresponding to stages like input processing, working memory, and long-term storage. With CIPM in hand, the once-bewildering maze of our mind becomes a journey of discovery, every neural pathway a route to understanding, every turn a step closer to unraveling the mysteries of human cognition.</p>
<p>As explorers of this mental labyrinth, armed with the map of CIPM, we are no longer wanderers but pioneers, decoding the intricate dance of neurons and synapses and unlocking the vast potential housed within the chambers of our minds.</p>
<h3>Browsing the Cognitive Library</h3>
<p>To truly understand the Cognitive Information Processing Model (CIPM), picture yourself stepping into the grandest library you can imagine. This isn’t just any library but an embodiment of the human mind’s vast information repository. Each section, shelf, and tome within this magnificent establishment mirrors the complex processes our brain undergoes every millisecond.</p>
<p>Step into the hallowed halls of the most expansive library you could fathom. But this is no ordinary library. Instead, it’s an intricate embodiment of the human brain’s vast network, a living testament to the Cognitive Information Processing Model (CIPM) in action.</p>
<p><strong>Input Processing — The Book Drop:</strong></p>
<p>As you push open the grand entrance, the cacophony of countless books being deposited greets you. These books, filled with narratives, facts, and fantasies, are handed over by diverse patrons, representing our five senses. Just as we soak in information from our surroundings, this intake counter is the starting point of every story, every piece of data that enters the library.</p>
<p><strong>Working Memory — The Sorting Table:</strong></p>
<p>Venture a little deeper, and you’ll find a bustling area teeming with librarians engrossed in their work. This is the majestic sorting table where each newly arrived book is given a once-over. Like our immediate cognitive faculties, these librarians sift through the information, categorizing it based on importance. Some are whisked away to reading nooks, some are earmarked for later, while others, perhaps too familiar or irrelevant, are set aside.</p>
<p><strong>Encoding Strategies — Highlighters and Notes:</strong></p>
<p>Observe closely, and you’ll find a select group of librarians engrossed in their books, armed with highlighters and pens. They’re the encoders, marking crucial passages, jotting down notes, and slipping bookmarks between pages. Their role? To ensure that the most vital information stands out, ready to be accessed when needed, mirroring our brain’s method of emphasizing specific memories or facts over others.</p>
<p><strong>Long-term Storage — The Vast Archives:</strong></p>
<p>Wander beyond the immediate hustle and bustle, and the library expands into a sprawling maze of towering shelves. Here, in these silent aisles, books find their permanent homes. Each section, whether an alcove dedicated to childhood memories or a vast hall of skills acquired over a lifetime, is a testament to our brain’s remarkable ability to store, catalog, and preserve vast amounts of information. Though some books might gather dust, they are always remembered.</p>
<p><strong>Information Retrieval — The Catalog System:</strong></p>
<p>Its heart lies at the library’s core — a sophisticated catalog system blending the traditional with the modern. Patrons approach with queries, and this system, be it through card indexes or digital touchpoints, points them to their desired knowledge. This mirrors our conscious mind’s quest for specific memories or facts, sifting through the expansive database and pinpointing the exact location of the needed information.</p>
<p>As you stroll through this magnificent library, remember that it’s a living, breathing representation of CIPM — structured yet fluid, vast yet organized. Every book added or retrieved, with every highlighted passage, tells the tale of our minds’ remarkable dance between knowledge and memory. This library captures the essence of human cognition, an ever-evolving realm, an ode to our unending quest for understanding.</p>
<p>The elegance of CIPM, much like our library analogy, lies in its structured yet fluid nature. It’s a system where information flows seamlessly, from the moment it enters our consciousness to its storage in the deep recesses of our minds, ready to be retrieved when summoned. This grand library of the human mind is ever-evolving, with new books added, old ones revisited, and the eternal dance of knowledge and memory playing out on its marble floors.</p>
<h3>The Essence of Cognitive Frameworks</h3>
<p>In human cognition and the vast cerebral landscape, a pressing question arises: why, amidst the intuitive nature of our thoughts and actions, do we need structured models like CIPM? To find the answer, let’s traverse the familiar corridors of our cognitive library.</p>
<p><strong>The Inherent Complexity of the Mind — The Infinite Collection:</strong></p>
<p>In all its glory, the human mind resembles an extensive library with no apparent end, brimming with books yet to be written and rooms yet to be explored. As intuitive beings, we can often navigate the primary corridors, instinctively retrieving a book or recalling a memory. But the vast recesses, the intertwined hallways, and the subtle nuances of each shelf and aisle can be overwhelming. Just as a visitor to our magnificent library could be easily lost amidst the endless collections, our understanding of the mind can often be superficial, limited to what’s evident and immediate.</p>
<p><strong>The Need for a Guide — Structuring Chaos:</strong></p>
<p>Stepping into a library with direction and categorization can be daunting. Every piece of information, every emotion, and every thought needs a designated place. With a structured system or a map, our innate capabilities might graze the surface. CIPM, in this context, serves as that essential catalog system. It gives order to chaos, coherence to randomness, and, most importantly, an insight into the depths and intricacies of cognitive functions.</p>
<p><strong>Bridging Thought and Action — The Librarian’s Role:</strong></p>
<p>The key to understanding our behavior and responses lies at the intersection of thought and deed. Picture the librarians in our cognitive library. They don’t merely sort or store books. They’re the dynamic force, guiding patrons, offering references, and ensuring a seamless flow of information. Similarly, CIPM acts as this guiding force, elucidating abstract neural impulses and thought patterns and transforming them into tangible actions, behaviors, and responses. It highlights the journey of information from being mere sensory input to an encoded memory or an executed action.</p>
<p><strong>A Mirror to Reflect and Refine:</strong></p>
<p>Every library, irrespective of its grandeur, requires regular audits, reshuffling, and updates. It’s a dynamic entity that evolves with time, adapting to the changing needs of its patrons. The human mind is no different. Our cognitive processes shift and transform as we evolve and learn. Models like CIPM help us comprehend the current state of our cognition and offer a reflective tool to refine and enhance our mental faculties.</p>
<p>As you meander through the vast halls of our mind’s library, appreciating the exquisite dance of neurons and synapses, remember the silent orchestrator behind the scenes — the Cognitive Information Processing Model. It’s the bridge, the guide, and the key to unlocking the myriad treasures housed within the labyrinthine recesses of human cognition. With such frameworks, we don’t merely observe or wander; we delve deep, understanding and mastering the art of thinking, feeling, and being.</p>
<h3>Stories Told Within the Shelves</h3>
<p>Every grand library boasts a plethora of tales, genres, and authors. Each book offers the Cognitive Information Processing Model (CIPM) and valuable insights across various disciplines and domains. Venture with me through these halls, and discover the universal tales CIPM tells.</p>
<p><strong>Tales of Learning — CIPM in Education:</strong></p>
<p>Enter a vibrant section where the pages whisper tales of curious learners and passionate teachers. CIPM shines on students’ information journeys, guiding educators to craft resonating lessons. It’s about positioning a story where it captivates its intended audience, ensuring each lesson isn’t merely taught but indeed remembered.</p>
<p><strong>Whispers of the Mind — CIPM in Psychology and Therapy:</strong></p>
<p>Wander into a more serene aisle where tales of emotions, memories, and human behavior reside. With the map of CIPM, therapists delve deeper into these narratives, decoding the intricate plots of the human psyche. It’s akin to reading between the lines, understanding the context, the characters, and the crescendos of every personal story.</p>
<p><strong>Chronicles of Tomorrow — CIPM in Technology and AI:</strong></p>
<p>Step into a futuristic section gleaming with digital tales. Here, CIPM charts out narratives for machines, guiding developers to script AI stories that echo human cognition. Like turning parchment to pixels, this section ensures that even age-old tales get a modern, interactive retelling.</p>
<p><strong>Ballads of the Heart — CIPM in Creative Endeavors:</strong></p>
<p>Stories of art, passion, and creativity come alive in a cozy nook. Using the CIPM guide, artists craft tales that tug at heartstrings, painting shared experiences and collective memories. Each artwork or novel in this section speaks to its beholders’ shared emotions and experiences.</p>
<p><strong>The Chronicles of the Everyday — CIPM in Daily Decisions:</strong></p>
<p>There exists a section frequented by many — tales of the everyday. It speaks of choices made, paths taken, and life’s simple moments. With CIPM as our compass, we navigate these daily narratives better, making choices that resonate with our life stories. Like the most-read books in a library, these tales guide our everyday decisions, grounding us in the wisdom of the ages.</p>
<p>As we journey through each aisle and chapter of this grand cognitive library, it becomes evident that CIPM’s tales are not just theoretical musings. They are stories that intertwine with our lives, our dreams, and our realities. Like a library that holds tales for every reader, CIPM offers insights for everyone, marking it as not just a model but a timeless storyteller across myriad landscapes.</p>
<h3>Self-Guided Journeys Within the Cognitive Library</h3>
<p>In the vast, sprawling library of the mind, each individual holds a unique collection of stories, insights, and experiences. Yet, just as a first-time visitor might feel overwhelmed by the towering shelves and endless aisles of a physical library, we might also feel daunted by the labyrinthine pathways of our cognition. How can we, as patrons of our mental libraries, navigate such intricacies and access the information we seek?</p>
<p><strong>The Directory — Recognizing Emotions:</strong></p>
<p>Start at the very entrance, where a helpful directory stands. Imagine being flustered after a particularly challenging day but unable to discern the exact emotion. Consulting the directory (or, in personal cognitive terms, taking a moment of introspection) can help pinpoint that you’re not just upset but perhaps feeling a combination of exhaustion, disappointment, and anxiety. Like identifying the right section of a library to find a specific genre, recognizing our emotions allows a more focused exploration of the mind.</p>
<p><strong>The Reference Desk — Understanding Behavior Patterns:</strong></p>
<p>Venture deeper into the library, and one finds the reference desk — the domain of librarians well-versed in the collection’s contents. You’ve noticed a pattern in your behavior — perhaps procrastinating essential tasks. Consulting the “librarian” (or reflecting upon past experiences) might reveal that this isn’t mere laziness. Instead, it might stem from a fear of failure. Like asking a librarian about a book’s context and background, diving deeper into our behaviors clarifies underlying causes.</p>
<p><strong>Special Collections — Deciphering Complex Memories:</strong></p>
<p>At the heart of the library, behind secured doors, lie the special collections — rare, delicate, or complex items that need careful handling. Similarly, in the depths of our cognition, there are memories — some cherished, others traumatic. Revisiting these requires care. Imagine understanding why a particular scent or song evokes such intense emotions. Using the CIPM map, one can trace back to the roots of these memories, perhaps uncovering forgotten moments from childhood or pivotal events in adolescence. Like accessing a rare manuscript, understanding these complex memories offers insights into the narrative of our lives.</p>
<p><strong>The Archival Room — Synthesizing Life Lessons:</strong></p>
<p>The archival room holds ancient scrolls and records in the library’s deepest recesses. Similarly, our mind holds life lessons and wisdom acquired over the years. Piecing together these teachings might require a holistic view. Let’s consider a more complicated scenario, like choosing a career path. By delving deep into the archives, examining past successes, failures, passions, and fears, one can synthesize a clearer vision for the future. It’s akin to synthesizing fragments from various texts to understand history comprehensively.</p>
<p>To traverse the personal library of cognition is more than just to wander amidst dusty shelves. With the map CIPM provides, we can embark on guided journeys, exploring the corners and corridors of our minds with purpose and clarity. Whether seeking a simple answer or deciphering life’s more profound mysteries, the Cognitive Information Processing Model serves as our compass, ensuring we never lose our way in the ever-evolving story of self.</p>
<h3>The Cognitive Library in Real-World Applications</h3>
<p>In the sprawling chambers of the Cognitive Library, abstract neural pathways find palpable representation. This metaphorical library, teeming with knowledge and memory, is more than just a sanctuary of introspection; it mirrors our worldly interactions, decisions, and creations. It forms the backdrop against which our daily lives play out, providing the scripts, the narratives, and the directions. Let’s decipher the threads intertwining this cognitive framework with our tangible existence.</p>
<h3>Searching the Library’s Sections</h3>
<p><strong>Decision Making — The Reference Section</strong></p>
<p>When life presents a crossroad of choices, our brain, like a diligent researcher, turns to its ‘reference section’ and ‘critical analysis corner.’ Here, by juxtaposing new data with archived experiences and analyzing them with logic, we sculpt our decisions, refining them for optimal outcomes.</p>
<p><strong>Learning a New Skill — The New Arrivals Shelf:</strong></p>
<p>As we embrace a new hobby or skill, it’s like ushering new volumes into our library. The brain’s dance between the entryway (initial impression) and the ‘new arrivals’ shelf (recently acquired knowledge) ensures fresh data is well-organized, easily accessible, and primed for application.</p>
<p><strong>Emotional Responses — A Sojourn into the Sentimental Alcove:</strong></p>
<p>Within the library’s deeper recesses lies the ‘sentimental alcove,’ a space rich with emotions and memories. As we confront powerful emotional stimuli, our cognitive self ventures here, letting past sentiments shape and guide our present reactions.</p>
<p><strong>Creativity and Innovation — Flourishing in the Imagination Wing:</strong></p>
<p>The ‘imagination wing,’ awash in colors, dreams, and abstract notions, is where ideas defy convention. Artists, inventors, and thinkers frequent this space, letting disparate thoughts collide, coalesce, and catalyze groundbreaking creations.</p>
<p><strong>Social Interactions — The Bustle of the Discussion Rooms:</strong></p>
<p>Our library isn’t solely a domain of solitary musing. The ‘discussion rooms’, brimming with discourse and debate, mirror our societal interactions. Armed with insights about emotions, intentions, and societal cues, we forge bonds, engage in vibrant dialogues, and strengthen communal ties.</p>
<p><strong>Personal Growth — Self-discovery in the Self-Help Aisle:</strong></p>
<p>For those on a journey of self-improvement, the ‘self-help aisle’ beckons. Just as these shelves are laden with tools for growth, our cognitive realm has its innate mechanisms of introspection, self-awareness, and evolution, urging us to be better versions of ourselves.</p>
<h3>Melding the Cognitive Library with Reality</h3>
<p><strong>Regular Audits &amp; Periodic Reflection:</strong></p>
<p>A library’s vitality hinges on timely audits. Likewise, routine self-reflection ensures that our cognitive apparatus remains updated, removing outdated beliefs and incorporating fresh perspectives.</p>
<p><strong>Interdisciplinary Explorations:</strong></p>
<p>Dipping into diverse sections of our library equates to embracing varied fields of knowledge in life. This interdisciplinary approach augments creativity, widens horizons and sharpens problem-solving prowess.</p>
<p><strong>Active Participation &amp; Social Engagements:</strong></p>
<p>Being part of library clubs mirrors our lives’ essence of social interaction. Collaborative learning, rich discussions, and exposure to myriad viewpoints enrich our cognitive tapestry.</p>
<p><strong>Digital Adaptation &amp; Modern Cognition:</strong></p>
<p>The world’s digital pivot parallels the library’s e-resource section. Leveraging technology amplifies our cognitive reach, making us adept navigators of the modern era.</p>
<p>We discern a vivid pattern in this grand confluence of the Cognitive Library and science. The library’s architecture, sections, and operations are not mere metaphors but actionable blueprints. By deftly managing our ‘cognitive inventory,’ we can ensure that our thoughts transcend abstraction, metamorphosing into impactful, tangible actions that shape our natural world.</p>
<h3>CIPM and the Cognitive Library of Tomorrow</h3>
<p>As the horizon’s golden hue silhouettes the Cognitive Library, it emerges not just as a tower of the past and present but as a beacon illuminating the vast terrains of the future. The library, mirroring the Cognitive Information Processing Model (CIPM), thrives on evolution, absorbing innovations, adapting to new paradigms, and promising unparalleled syntheses of cognition, technology, and science.</p>
<h4>The Digital Renaissance: Harnessing Tech’s Potential</h4>
<p>The Digital Room, an emblem of modern-day convergence in our library, is set to burgeon, reflecting the uncharted territories of AI and neuroscience.</p>
<p>**AI Symbiosis:**As AI achieves new pinnacles, the CIPM is primed to transform as a lighthouse guiding more nuanced machine learning journeys. Think of it as the library digitizing its oldest, most valuable manuscripts, rendering them indestructible and accessible to every curious mind across the globe.</p>
<p>**Neuroscientific Revelations:**With each layer of the brain we unveil, the CIPM is refined, capturing cognitive intricacies. This is akin to our library employing immersive multimedia — patrons don’t just read about a historical battle; they experience its adrenaline through AR or relive a classic novel via VR.</p>
<h4>The Structural Evolution: A Library in Flux</h4>
<p>The essence of the Cognitive Library transcends its vast collection. Its very foundation, walls, and domes echo metamorphosis.</p>
<p><strong>Fluidic Frameworks:</strong> New cognitive theories and insights may sculpt the CIPM into a more fluid model. Picture our library’s modular architecture, reconfigurable alcoves, and dynamic spaces that shift and adapt to the ever-evolving knowledge landscape.</p>
<p><strong>Interdisciplinary Annexes:</strong> As the tendrils of biotechnology, quantum mechanics, and neuropsychology intertwine, the library expands, adding wings that house knowledge and foster synthesis. Each annex becomes a crucible, melding disparate disciplines into unified narratives.</p>
<p><strong>Sustainable Cognition:</strong> The Cognitive Library paves paths for mental sustainability by mirroring the global thrust towards eco-conscious. Spaces dedicated to cognitive rejuvenation and resilience echo real-world green terraces, sustainable energy sources, and harmonious living principles.</p>
<h4>Epilogue: The Library as an Eternal Luminar</h4>
<p>The Cognitive Library, our tangible manifestation of the CIPM, is not merely a knowledge sanctuary. It pulsates, lives, and evolves — embracing the old, welcoming the new, and foreshadowing realms unknown.</p>
<p>In the intricate ballet of cognition, technology, and empirical discovery, the library is both a spectator and a maestro, guiding us, enlightening pathways, and kindling aspirations. It’s a testament that our quest to fathom the human psyche is ceaseless, filled with revelations and wonders. As we bookmark this segment of our journey, we’re reminded that every conclusion is a prelude, every end a fresh dawn in the enduring epic of the Cognitive Library.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/cipm-the-cognitive-information-processing-model">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>Protecting Routes in Next.js 13</title>
      <link>https://zachshallbetter.com/writing/protecting-routes-in-next-js-13</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/protecting-routes-in-next-js-13</guid>
      <pubDate>Tue, 04 Jul 2023 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>With the evolution of the App Router in Next.js, the framework has become even more robust, offering developers enhanced control over…</description>
      <content:encoded><![CDATA[<p>With the evolution of the App Router in Next.js, the framework has become even more robust, offering developers enhanced control over routing and the ability to protect routes more efficiently. This article will delve deep into how to protect routes in Next.js using the App Router (Next 13.4), covering the latest features such as Middleware, <code>exportMode</code>, <code>unstable_cache</code>, and more. This guide is intended for senior developers with a good understanding of Next.js and React.</p>
<blockquote>
<p>This article is for personal reference— your mileage may vary!</p>
</blockquote>
<p><em>Complete examples can be found in the associated Gist. You can find them here:</em><a href="https://gist.github.com/zachshallbetter/669729a37e66f277147b2fb864d921ee">https://gist.github.com/zachshallbetter</a><em>.</em></p>
<h3>The App Router</h3>
<p>Next.js is a popular framework for building React applications that support server-side rendering, static site generation, and incremental static regeneration. One of the features that Next.js provides is the App component, which allows you to customize the rendering of your pages and share state across them.</p>
<p>The App Router is a feature in Next.js that allows developers to handle routing more centrally and efficiently. It provides a single place (the app directory) to define routes and their corresponding components. This makes it easier to manage routes and allows for advanced routing features like transitions, nesting, and route protection.</p>
<h3>Changes in Configuration</h3>
<h4>Replacing <code>output</code> with <code>exportMode</code></h4>
<p>The <code>output</code> option in <code>next.config.js</code> is deprecated and replaced by <code>exportMode</code>. Here&#39;s how you can use the new option:</p>
<pre><code>module.exports = {
  exportMode: &amp;#x27;your-value&amp;#x27;,
};
</code></pre>
<h4>Replacing <code>generateStaticParams</code> with <code>getStaticPaths</code></h4>
<p>The <code>generateStaticParams</code> function is no longer required and replaced by <code>getStaticPaths</code>. Here&#39;s how you can use the new function:</p>
<pre><code>export async function getStaticPaths() {
  // Your logic here
}
</code></pre>
<h4>Replacing <code>fetch</code> with <code>unstable_cache</code></h4>
<p>The <code>fetch</code> function is no longer automatically memoized and replaced by <code>unstable_cache</code>. Here&#39;s how you can use the new feature:</p>
<pre><code>import { unstable_cache } from &amp;#x27;next/fetch&amp;#x27;;

export async function getServerSideProps() {
  const data = await unstable_cache(&amp;#x27;your-api-url&amp;#x27;);
  return { props: { data } };
}
</code></pre>
<h4>Replacing <code>revalidateTag</code> with <code>revalidate</code></h4>
<p>The <code>revalidateTag</code> function is no longer available and has been replaced by <code>revalidate</code>. Here&#39;s how you can use the new function:</p>
<pre><code>export async function getStaticProps() {
  // Your logic here
  return {
    revalidate: 10, // Time in seconds
  };
}
</code></pre>
<h3>Protecting Pages, Components, and APIs with Middleware</h3>
<p>The <code>Route Handlers</code> feature is no longer supported and replaced by <code>Middleware</code>. Here&#39;s how you can use Middleware to protect pages, components, and APIs:</p>
<pre><code>import { NextResponse } from &amp;#x27;next/server&amp;#x27;;

export function authMiddleware(req) {
  // Add your own logic here to check if the user is authenticated
  const userIsAuthenticated = checkUserAuthentication();

  if (!userIsAuthenticated) {
    return NextResponse.redirect(&amp;#x27;/login&amp;#x27;);
  }

  return NextResponse.next();
}
</code></pre>
<p>In this example, we define an <code>authMiddleware</code> function that checks if the user is authenticated. If not, it redirects them to the login page. We then import this function into our pages and API routes and apply it using <code>authMiddleware(req)</code>.</p>
<h3>Using the App Component to Protect Routes in Next.js 13.4</h3>
<p>The App component is a special component that Next.js uses to initialize pages. It receives props such as Component, pageProps, router, and err, and it can return any React element. The Component prop is the active page component, and the pageProps prop is the props that are passed to it. The router prop is an instance of the Next.js router, which exposes methods and properties such as push, replace, pathname, query, and asPath. The err prop is an optional error object that is only defined when an error occurs during rendering.</p>
<p>One of the benefits of using the App component is that it allows you to wrap your pages with a common layout or a provider component. For example, you can use the App component to add a header and a footer to all your pages, or to provide a global context or a theme to your application. To use the App component, you need to create a file called <code>_app.js</code> (or <code>_app.tsx</code> if you are using TypeScript) in the pages directory and export a default function or class component.</p>
<p>To protect routes that require authentication or authorization, we can use the App component to check the user’s status and redirect them to a login page or an error page if they are not authorized to access the current page. To do this, we need to use two hooks: <code>useRouter</code> and <code>useEffect</code>. The <code>useRouter</code> hook returns the router object that we can use to access the current route information and perform navigation. The <code>useEffect</code> hook allows us to execute a side effect after the component renders.</p>
<p>The basic idea is to use <code>useEffect</code> to check the user&#39;s status and compare it with the required status for the current route. If they don&#39;t match, we can use <code>router.replace</code> to redirect the user to another page. We can also use <code>router.events.on(&#39;routeChangeStart&#39;, callback)</code> to listen for route changes and perform the same check before rendering the new page. Here is an example of how we can implement this logic in the App component:</p>
<pre><code>import { useRouter } from &amp;#x27;next/router&amp;#x27;;
import { useEffect } from &amp;#x27;react&amp;#x27;;

function MyApp({ Component, pageProps }) {
  const router = useRouter();

  useEffect(() =&gt; {
    const handleRouteChange = (url) =&gt; {
      // Add your own logic here to check if the user is authenticated
      const userIsAuthenticated = checkUserAuthentication();

      if (!userIsAuthenticated &amp;&amp; url === &amp;#x27;/protected-page&amp;#x27;) {
        router.replace(&amp;#x27;/login&amp;#x27;);
      }
    };

    router.events.on(&amp;#x27;routeChangeStart&amp;#x27;, handleRouteChange);

    return () =&gt; {
      router.events.off(&amp;#x27;routeChangeStart&amp;#x27;, handleRouteChange);
    };
  }, []);

  return &lt;Component {...pageProps} /&gt;;
}

export default MyApp;
</code></pre>
<p>We have implemented a simple way to protect routes in Next.js with the App component. You may need to customize it according to your needs and preferences. For example, you may want to use a different way to store and retrieve the user’s token, or you may want to use a different logic to determine the required status for each route. You may also want to handle some edge cases or errors.</p>
<p>Here’s the code:</p>
<pre><code>import { useRouter } from &amp;#x27;next/router&amp;#x27;
import { useEffect } from &amp;#x27;react&amp;#x27;

function getUserStatus(token) {
  if (token === &amp;#x27;admin&amp;#x27;) {
    return &amp;#x27;admin&amp;#x27;
  } else if (token === &amp;#x27;user&amp;#x27;) {
    return &amp;#x27;user&amp;#x27;
  } else {
    return &amp;#x27;guest&amp;#x27;
  }
}

function getRequiredStatus(pathname) {
  if (pathname === &amp;#x27;/admin&amp;#x27;) {
    return &amp;#x27;admin&amp;#x27;
  } else if (pathname === &amp;#x27;/profile&amp;#x27;) {
    return &amp;#x27;user&amp;#x27;
  } else {
    return &amp;#x27;guest&amp;#x27;
  }
}

export default function App({ Component, pageProps }) {
  const router = useRouter()

  function checkAuth() {
    const token = localStorage.getItem(&amp;#x27;token&amp;#x27;)
    const userStatus = getUserStatus(token)
    const requiredStatus = getRequiredStatus(router.pathname)

    if (userStatus !== requiredStatus) {
      if (userStatus === &amp;#x27;guest&amp;#x27;) {
        router.replace(&amp;#x27;/login&amp;#x27;)
      } else {
        router.replace(&amp;#x27;/error&amp;#x27;)
      }
    }
  }

  useEffect(() =&gt; {
    checkAuth()
  }, [])

  useEffect(() =&gt; {
    const handleRouteChange = () =&gt; {
      checkAuth()
    }

    router.events.on(&amp;#x27;routeChangeStart&amp;#x27;, handleRouteChange)

    return () =&gt; {
      router.events.off(&amp;#x27;routeChangeStart&amp;#x27;, handleRouteChange)
    }
  }, [])

  return &lt;Component {...pageProps} /&gt;
}
</code></pre>
<h3>Using Middleware.js to Protect Routes in Next.js 13.4</h3>
<p>Another way to protect routes in Next.js is to use middleware.js. Middleware.js allows you to run code before rendering a page on both the server and the client. You can use middleware.js to perform authentication, authorization, redirection, caching, or any other logic needed before rendering a page.</p>
<p>To use middleware.js, create a file called <code>_middleware.js</code> (or <code>_middleware.ts</code> if you are using TypeScript) in the pages directory and export a default function that receives a <code>NextRequest</code> object and returns a <code>NextResponse</code> object or nothing.</p>
<p>To protect routes with middleware.js, we can use a similar logic as we did with the App component. We can check the user’s status and compare it with the required status for the current route. If they don’t match, we can use <code>NextResponse.redirect</code> to redirect the user to another page.</p>
<p>Example code for middleware.js:</p>
<pre><code>import { NextRequest, NextResponse } from &amp;#x27;next/server&amp;#x27;

function getUserStatus(token) {
  if (token === &amp;#x27;admin&amp;#x27;) {
    return &amp;#x27;admin&amp;#x27;
  } else if (token === &amp;#x27;user&amp;#x27;) {
    return &amp;#x27;user&amp;#x27;
  } else {
    return &amp;#x27;guest&amp;#x27;
  }
}

function getRequiredStatus(pathname) {
  if (pathname === &amp;#x27;/admin&amp;#x27;) {
    return &amp;#x27;admin&amp;#x27;
  } else if (pathname === &amp;#x27;/profile&amp;#x27;) {
    return &amp;#x27;user&amp;#x27;
  } else {
    return &amp;#x27;guest&amp;#x27;
  }
}

export default function middleware(req) {
  const token = req.cookies.token
  const userStatus = getUserStatus(token)
  const requiredStatus = getRequiredStatus(req.nextUrl.pathname)

  if (userStatus !== requiredStatus) {
    if (userStatus === &amp;#x27;guest&amp;#x27;) {
      return NextResponse.redirect(&amp;#x27;/login&amp;#x27;)
    } else {
      return NextResponse.redirect(&amp;#x27;/error&amp;#x27;)
    }
  }
}
</code></pre>
<p>This approach has advantages over using the App component, such as being faster, more flexible, and more secure. However, it also has some limitations, such as not being able to access React components or hooks or not being able to run on older browsers that don’t support ES modules. You can read more about middleware.js and its features and caveats in the official documentation.</p>
<h3>Conclusion</h3>
<p>The new App Router in Next.js provides a powerful and efficient way to handle routing and protect routes in your application. By using Middleware, <code>exportMode</code>, <code>unstable_cache</code>, and other new features, you can ensure that only authenticated users can access certain pages, components, and API endpoints. This not only enhances the security of your application but also provides a better user experience by directing users to the appropriate pages based on their authentication status.</p>
<p>Remember, the key to effectively using the App Router is understanding your application’s routing requirements and implementing the appropriate checks at each route. With a good understanding of the App Router and the examples in this guide, you should be well-equipped to protect routes in your Next.js application.</p>
<p>You can check out the official documentation for more information on the App Router in Next.js. Happy coding!</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/protecting-routes-in-next-js-13">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>WTF is React Fiber?</title>
      <link>https://zachshallbetter.com/writing/wtf-is-react-fiber</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/wtf-is-react-fiber</guid>
      <pubDate>Thu, 04 May 2023 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>React Fiber has the buzzword vibe. In this article, I’ll attempt to unravel the mystery, explore its inner workings, and describe why it’s…</description>
      <content:encoded><![CDATA[<p>React Fiber has the <em>buzzword</em>vibe. In this article, I’ll attempt to unravel the mystery, explore its inner workings, and describe why it’s a game-changer for React developers. I’ll also provide comparative code examples to illustrate the differences between the traditional React reconciliation algorithm and React Fiber.</p>
<hr>
<h3>What is React Fiber?</h3>
<p>React Fiber is the new reconciliation algorithm introduced in React v16. It’s a complete overhaul of React’s core algorithm, determining how and when to update the DOM based on changes in the component tree.</p>
<p>Previously, React used a “stack” reconciliation algorithm that processed updates synchronously. While suitable for most use cases, this approach struggled with complex updates, animations, and user interactions.</p>
<p>React Fiber introduces “fibers” as the fundamental units of work, allowing React to break down render functions into smaller chunks and prioritize them based on importance.</p>
<h3>Key Features</h3>
<ul>
<li><p>Asynchronous Rendering: React Fiber enables asynchronous rendering, allowing React to work on multiple tasks concurrently. This ensures the main thread remains responsive, even during long-running rendering tasks.</p>
</li>
<li><p>Time-Slicing: Time-slicing allows React to split rendering work into small chunks and interleave them with other tasks. This ensures high-priority updates, such as user interactions and animations, are processed quickly, while lower-priority updates can be deferred.</p>
</li>
<li><p>Suspense: Suspense enables developers to handle asynchronous data fetching and rendering more gracefully by specifying fallback content displayed while data is fetched or components are loaded.</p>
</li>
<li><p>Concurrent Mode (Experimental): Concurrent Mode allows React to work on multiple tasks concurrently, enabling features like interruptible rendering and selective updates.</p>
</li>
<li><p>Error Boundaries: Error boundaries catch JavaScript errors in their child component tree, log those errors, and display a fallback UI. This feature helps developers handle errors gracefully and prevent entire applications from crashing.</p>
</li>
</ul>
<h3>Traditional React Reconciliation</h3>
<p>Traditional React reconciliation processes updates synchronously, which can lead to unresponsiveness during complex rendering tasks.</p>
<pre><code>class App extends React.Component {
  state = { data: [] };

  componentDidMount() {
    // Fetch data and update state
    fetchData().then((data) =&gt; {
      this.setState({ data });
    });
  }

  render() {
    return (
      &lt;div&gt;
        {/* Render data */}
        {this.state.data.map((item) =&gt; (
          &lt;div key={item.id}&gt;{item.name}&lt;/div&gt;
        ))}
      &lt;/div&gt;
    );
  }
}
</code></pre>
<h3>React Fiber with Suspense and Concurrent Mode</h3>
<p>React Fiber, combined with Suspense and Concurrent Mode, handles asynchronous rendering gracefully while ensuring smooth user interaction.</p>
<pre><code>import { Suspense } from &amp;#x27;react&amp;#x27;;

const DataComponent = React.lazy(() =&gt; import(&amp;#x27;./DataComponent&amp;#x27;));

function App() {
  return (
    &lt;div&gt;
      &lt;Suspense fallback={&lt;div&gt;Loading...&lt;/div&gt;}&gt;
        {/* Render data using lazy-loaded component */}
        &lt;DataComponent /&gt;
      &lt;/Suspense&gt;
    &lt;/div&gt;
  );
}

// DataComponent.js
import React, { useState, useEffect } from &amp;#x27;react&amp;#x27;;

function DataComponent() {
  const [data, setData] = useState([]);

  useEffect(() =&gt; {
    // Fetch data and update state
    fetchData().then((fetchedData) =&gt; {
      setData(fetchedData);
    });
  }, []);

  return (
    &lt;div&gt;
      {/* Render data */}
      {data.map((item) =&gt; (
        &lt;div key={item.id}&gt;{item.name}&lt;/div&gt;
      ))}
    &lt;/div&gt;
  );
}

async function fetchData() {
  // Simulate data fetching
  return new Promise((resolve) =&gt; {
    setTimeout(() =&gt; {
      resolve([{ id: 1, name: &amp;#x27;Item 1&amp;#x27; }, { id: 2, name: &amp;#x27;Item 2&amp;#x27; }]);
    }, 1000);
  });
}

export default DataComponent;
</code></pre>
<p>In this example, we use React.lazy to load the <code>DataComponent</code> and wrap it with the <code>Suspense</code> component. The fallback prop specifies the content displayed while the data fetch or component rendering completes, allowing us to handle asynchronous rendering gracefully and improve the user experience.</p>
<h3>Traditional React Approach for Data Fetching</h3>
<p>Traditional React applications typically handle data fetching using lifecycle methods such as componentDidMount. Developers fetch data asynchronously and update the component’s state using the setState method, triggering a re-render and displaying the fetched data in the user interface.</p>
<pre><code>import React, { Component } from &amp;#x27;react&amp;#x27;;

class DataComponent extends Component {
  state = {
    data: null,
    isLoading: true,
    error: null,
  };

  componentDidMount() {
    // Fetch data asynchronously
    fetch(&amp;#x27;/api/data&amp;#x27;)
      .then((response) =&gt; {
        if (!response.ok) {
          throw new Error(&amp;#x27;Failed to fetch data&amp;#x27;);
        }
        return response.json();
      })
      .then((data) =&gt; {
        // Update state with fetched data and trigger re-render
        this.setState({ data, isLoading: false });
      })
      .catch((error) =&gt; {
        // Handle errors during data fetching
        this.setState({ error, isLoading: false });
      });
  }

  render() {
    const { data, isLoading, error } = this.state;

    if (isLoading) {
      return &lt;div&gt;Loading...&lt;/div&gt;;
    }

    if (error) {
      return &lt;div&gt;Error: {error.message}&lt;/div&gt;;
    }

    return (
      &lt;div&gt;
        {/* Render fetched data */}
        {data &amp;&amp; data.map((item) =&gt; (
          &lt;div key={item.id}&gt;{item.name}&lt;/div&gt;
        ))}
      &lt;/div&gt;
    );
  }
}

export default DataComponent;
</code></pre>
<p>While this traditional approach works for simple use cases, it struggles with complex asynchronous operations and providing a smooth user experience. Its advanced features, like Concurrent Mode, Suspense, and SuspenseList, address these limitations.</p>
<h3>React Fiber with Suspense for Data Fetching</h3>
<p>React Suspense can also be used for data fetching, allowing developers to handle asynchronous data fetching more gracefully by specifying fallback content while data is being loaded.</p>
<pre><code>import React, { useState, useEffect, Suspense } from &amp;#x27;react&amp;#x27;;

// Create a resource that reads data asynchronously
const createResource = (promise) =&gt; {
  let status = &amp;#x27;pending&amp;#x27;;
  let result;
  return {
    read() {
      if (status === &amp;#x27;pending&amp;#x27;) {
        throw promise;
      } else if (status === &amp;#x27;error&amp;#x27;) {
        throw result;
      } else if (status === &amp;#x27;success&amp;#x27;) {
        return result;
      }
    },
    resolve(data) {
      status = &amp;#x27;success&amp;#x27;;
      result = data;
    },
    reject(error) {
      status = &amp;#x27;error&amp;#x27;;
      result = error;
    },
  };
};

const fetchData = () =&gt; {
  return new Promise((resolve) =&gt; {
    setTimeout(() =&gt; {
      resolve([{ id: 1, name: &amp;#x27;Item 1&amp;#x27; }, { id: 2, name: &amp;#x27;Item 2&amp;#x27; }]);
    }, 1000);
  });
};

const resource = createResource(fetchData());

resource.promise = fetchData()
  .then(resource.resolve)
  .catch(resource.reject);

function DataComponent() {
  const data = resource.read();
  return (
    &lt;div&gt;
      {/* Render data */}
      {data.map((item) =&gt; (
        &lt;div key={item.id}&gt;{item.name}&lt;/div&gt;
      ))}
    &lt;/div&gt;
  );
}

function App() {
  return (
    &lt;div&gt;
      &lt;Suspense fallback={&lt;div&gt;Loading...&lt;/div&gt;}&gt;
        {/* Render data using Suspense */}
        &lt;DataComponent /&gt;
      &lt;/Suspense&gt;
    &lt;/div&gt;
  );
}

export default App;
</code></pre>
<p>In this example, we use the <code>componentDidMount</code> lifecycle method to fetch data asynchronously and update the component&#39;s state. The <code>isLoading</code> state variable displays a loading indicator while the data is being fetched. Once the data is available, we render it in the user interface.</p>
<p>While this traditional approach works well for simple use cases, it has limitations when handling complex asynchronous operations and providing a smooth user experience. This is where React Fiber, with its advanced features like Concurrent Mode, Suspense, and SuspenseList, comes into play.</p>
<h3>Traditional React Approach for Transitions</h3>
<p>Traditional React applications often use CSS animations or third-party libraries like React Transition Group to create transitions between states. However, these approaches may need to provide a higher level of control and responsiveness required for modern applications, particularly when dealing with complex rendering tasks or frequent updates.</p>
<pre><code>import React, { Component } from &amp;#x27;react&amp;#x27;;
import &amp;#x27;./App.css&amp;#x27;;

class App extends Component {
  state = {
    show: false,
  };

  toggleShow = () =&gt; {
    this.setState((prevState) =&gt; ({ show: !prevState.show }));
  };

  render() {
    const { show } = this.state;

    return (
      &lt;div className=&quot;App&quot;&gt;
        &lt;button onClick={this.toggleShow}&gt;Toggle&lt;/button&gt;
        &lt;div className={`box ${show ? &amp;#x27;show&amp;#x27; : &amp;#x27;hide&amp;#x27;}`}&gt;Content&lt;/div&gt;
      &lt;/div&gt;
    );
  }
}

export default App;
</code></pre>
<pre><code>/* App.css */
.box {
  opacity: 0;
  transition: opacity 0.3s ease-in-out;
}

.box.show {
  opacity: 1;
}

.box.hide {
  opacity: 0;
}
</code></pre>
<h3>React Fiber with Concurrent Mode and Transitions</h3>
<p>Concurrent Mode allows React to work on multiple tasks concurrently, enabling features like interruptible rendering and selective updates. One of the powerful features of Concurrent Mode is the ability to create smooth transitions between different states of the application. Let’s take a look at an example that demonstrates this capability:</p>
<pre><code>import React, { useState, useTransition, Suspense } from &amp;#x27;react&amp;#x27;;

// ... (same as previous example)

function App() {
  const [resource, setResource] = useState(null);
  const [startTransition, isPending] = useTransition({ timeoutMs: 3000 });

  const handleClick = () =&gt; {
    const nextResource = createResource(fetchData());
    nextResource.promise = fetchData()
      .then(nextResource.resolve)
      .catch(nextResource.reject);
    startTransition(() =&gt; {
      setResource(nextResource);
    });
  };

  return (
    &lt;div&gt;
      &lt;button onClick={handleClick}&gt;Fetch Data&lt;/button&gt;
      &lt;Suspense fallback={&lt;div&gt;Loading...&lt;/div&gt;}&gt;
        {/* Render data using Suspense */}
        {resource &amp;&amp; &lt;DataComponent resource={resource} /&gt;}
      &lt;/Suspense&gt;
      {isPending &amp;&amp; &lt;div&gt;Loading...&lt;/div&gt;}
    &lt;/div&gt;
  );
}

export default App;
</code></pre>
<p>The useTransition hook ensures a smooth and responsive user experience, even when fetching and rendering large amounts of data.</p>
<h3>Traditional React Approach for Handling Multiple Asynchronous Operations</h3>
<p>In traditional React applications, handling multiple asynchronous operations, such as fetching data for multiple components, often involves managing the loading state for each operation individually. This can lead to a suboptimal user experience, as components may render their fallback content or loading indicators at different times, creating a disjointed and potentially confusing interface.</p>
<pre><code>import React, { Component } from &amp;#x27;react&amp;#x27;;

class App extends Component {
  state = {
    data1: null,
    data2: null,
    loading1: true,
    loading2: true,
  };

  componentDidMount() {
    this.fetchData1();
    this.fetchData2();
  }

  fetchData1 = () =&gt; {
    setTimeout(() =&gt; {
      this.setState({ data1: &amp;#x27;Data 1&amp;#x27;, loading1: false });
    }, 1000);
  };

  fetchData2 = () =&gt; {
    setTimeout(() =&gt; {
      this.setState({ data2: &amp;#x27;Data 2&amp;#x27;, loading2: false });
    }, 2000);
  };

  render() {
    const { data1, data2, loading1, loading2 } = this.state;

    return (
      &lt;div className=&quot;App&quot;&gt;
        {loading1 ? &lt;div&gt;Loading item 1...&lt;/div&gt; : &lt;div&gt;{data1}&lt;/div&gt;}
        {loading2 ? &lt;div&gt;Loading item 2...&lt;/div&gt; : &lt;div&gt;{data2}&lt;/div&gt;}
      &lt;/div&gt;
    );
  }
}

export default App;
</code></pre>
<p>In this example, we use the componentDidMount lifecycle method to fetch data for two components. The loading1 and loading2 state variables control the visibility of the loading indicators for each component. The data is fetched with simulated delays, and the loading indicators are displayed until the data is ready.</p>
<p>React Fiber’s SuspenseList component addresses this limitation by providing a way to coordinate the revealed order of multiple Suspense components.</p>
<h3>Asynchronous Rendering with React Fiber’s SuspenseList</h3>
<p>In scenarios where multiple components are wrapped in Suspense and are fetching data concurrently, we can use the SuspenseList component to coordinate the revealed order of the fallback content. This allows us to control how and when the content is displayed to the user.</p>
<pre><code>import React, { Suspense, SuspenseList } from &amp;#x27;react&amp;#x27;;

// ... (same as previous examples)

function App() {
  return (
    &lt;div&gt;
      &lt;SuspenseList revealOrder=&quot;forwards&quot; tail=&quot;collapsed&quot;&gt;
        &lt;Suspense fallback={&lt;div&gt;Loading item 1...&lt;/div&gt;}&gt;
          &lt;DataComponent resource={resource1} /&gt;
        &lt;/Suspense&gt;
        &lt;Suspense fallback={&lt;div&gt;Loading item 2...&lt;/div&gt;}&gt;
          &lt;DataComponent resource={resource2} /&gt;
        &lt;/Suspense&gt;
      &lt;/SuspenseList&gt;
    &lt;/div&gt;
  );
}

export default App;
</code></pre>
<p>In this example, we use the SuspenseList component to wrap two Suspense components. The revealOrder prop specifies the order in which the fallback content is revealed (“forwards” means from first to last), and the tail prop specifies how the tail items (items after the first one) should be displayed (“collapsed” means they are hidden until the first item is ready).</p>
<p>This gives us fine-grained control over the loading experience and allows us to create more polished and user-friendly interfaces.</p>
<p>For those interested in diving deeper into React Fiber and its features, the official React documentation provides detailed explanations, guides, and examples to help developers maximize React Fiber and its capabilities.</p>
<p><strong>Official React Documentation:</strong></p>
<ul>
<li><p><a href="https://reactjs.org/docs/concurrent-mode-intro.html">React Concurrent Mode (Experimental)</a></p>
</li>
<li><p><a href="https://reactjs.org/docs/concurrent-mode-suspense.html">React Suspense</a></p>
</li>
<li><p><a href="https://reactjs.org/docs/code-splitting.html">Code Splitting with React.lazy</a></p>
</li>
<li><p><a href="https://reactjs.org/docs/concurrent-mode-reference.html#suspenselist">React SuspenseList</a></p>
</li>
<li><p><a href="https://reactjs.org/docs/error-boundaries.html">Error Boundaries in React</a></p>
</li>
</ul>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/wtf-is-react-fiber">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>Exploring React Fiber Use Cases</title>
      <link>https://zachshallbetter.com/writing/exploring-react-fiber-use-cases</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/exploring-react-fiber-use-cases</guid>
      <pubDate>Thu, 04 May 2023 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>React Fiber, introduced in React v16, is a complete rewrite of React’s core reconciliation algorithm. It significantly improves how React…</description>
      <content:encoded><![CDATA[<p>React Fiber, introduced in React v16, is a complete rewrite of React’s core reconciliation algorithm. It significantly improves how React handles rendering tasks, making it more efficient, flexible, and capable of handling complex use cases. React Fiber’s asynchronous rendering capabilities have allowed developers to create smooth and responsive user interfaces.</p>
<p>This article will explore some critical use cases where React Fiber shines and how it empowers developers to build better applications.</p>
<p>1<strong>Improved Animation and Transition Performance</strong>One of the most significant benefits of React Fiber is its ability to handle animations and transitions smoothly. Before React Fiber, animations in React applications could suffer from dropped frames and jankiness, especially when there were complex rendering tasks or frequent updates.</p>
<p>React Fiber’s asynchronous rendering allows it to prioritize animation-related updates over less critical tasks. This ensures that animations run smoothly, even with other updates.</p>
<p>Developers can leverage this capability to create applications with complex animations, interactive transitions, and smooth scrolling effects, all while maintaining a high level of performance.</p>
<p>2<strong>Handling Large Data Sets and Lists</strong>Rendering large data sets and lists can be challenging in any application. React Fiber’s ability to break down rendering work into smaller chunks and prioritize tasks based on importance makes it well-suited for handling large data sets.</p>
<p>With React Fiber, developers can implement features like virtualization and incremental rendering to render large lists and tables. Virtualization involves generating only the visible portion of a list, while incremental rendering progressively generates fragments.</p>
<p>These techniques help reduce the initial rendering time, improve the user experience, and prevent the application from becoming unresponsive.</p>
<p>3<strong>Time-Slicing and Concurrent Mode</strong>Time-slicing is a feature introduced in React Fiber that allows React to split rendering work into small chunks and interleave them with other tasks. This ensures the main thread remains responsive, even with long-running rendering tasks.</p>
<p>Concurrent Mode is an experimental feature in React that builds on the concept of time-slicing. It allows React to work on multiple tasks concurrently, enabling features like interruptible rendering and selective updates.</p>
<p>With Concurrent Mode, developers can build responsive applications even under heavy load, prioritize critical updates, and provide instant feedback to user interactions.</p>
<p>4<strong>Suspense and Lazy Loading</strong>React Fiber introduces the concept of Suspense, which allows developers to handle asynchronous data fetching and rendering more gracefully. Suspense enables developers to specify fallback content displayed while data is fetched or components are loaded.</p>
<p><code>React.lazy</code> is a built-in function that works with Suspense to enable code-splitting and lazy loading of components. This allows developers to load elements on-demand, reducing the initial bundle size and improving the application’s loading performance.</p>
<p>Suspense and React.lazy are potent tools for handling asynchronous operations and improving the user experience in data-driven applications.</p>
<p>5**Streaming Server-Side Rendering (sSSR)**React Fiber also brings improvements to server-side rendering (sSSR) for building React components on the server and sending the generated HTML to the client, improving the initial page load performance and SEO.</p>
<p>React Fiber’s streaming sSSR feature allows developers to send rendered HTML to the client in chunks as they become available. This reduces the time to the first byte and improves the perceived performance of the application.</p>
<p>Streaming SSR is especially useful for applications with dynamic content, where different parts of the page may be rendered based on user data or server responses.</p>
<p>6<strong>Error Boundaries and Graceful Error Handling</strong>React Fiber introduces the concept of error boundaries, which are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI. This feature allows developers to handle errors gracefully and prevent the entire application from crashing.</p>
<p>Developers can define error boundaries by creating a class component with a <code>componentDidCatch</code> lifecycle method. This method is triggered when an error occurs in child components, allowing developers to handle the error and render a fallback UI.</p>
<p>Creating smooth animations, handling large data sets, implementing lazy loading, and server-side rendering are baseline requirements these days. React Fiber provides the tools and flexibility needed to build modern and responsive applications.</p>
<p>React Documentation and Additional Information:- <a href="https://reactjs.org/docs/concurrent-mode-intro.html">React Concurrent Mode (Experimental)</a>- <a href="https://reactjs.org/docs/concurrent-mode-suspense.html">React Suspense</a>- <a href="https://reactjs.org/docs/code-splitting.html">Code Splitting with React.lazy</a>- <a href="https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html">React Server Components (Experimental)</a>- <a href="https://reactjs.org/docs/error-boundaries.html">Error Boundaries in React</a></p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/exploring-react-fiber-use-cases">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>Slack is Destroying Communities</title>
      <link>https://zachshallbetter.com/writing/slack-is-destroying-communities</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/slack-is-destroying-communities</guid>
      <pubDate>Sat, 16 Feb 2019 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>How the world’s best business collaboration tool alienated one of the world’s largest web developer communities.</description>
      <content:encoded><![CDATA[<p>In January 2015, through a partnership between the teams at <a href="https://uxiliary.com">Uxiliary</a> and <a href="https://inlandnorthwest.tech">INT</a>, we launched one of the early public communities on Slack. At that time, Slack’s platform was gaining popularity as users discovered it was better than any collaboration tool that had previously existed. Our users loved it and encouraged colleagues to jump in, which drew entire businesses to join both Slack and us. We were lucky to catch Slack’s wave, and as a result, we quickly grew a vibrant community of web programmers.</p>
<p>During this time we synced with new friends and built a team of experts that aided in the group’s management. It required a surprising amount of dedication, but the positive contribution we were providing the Web Developer community motivated us. After some time, it operated with little intervention or management and continued to grow.</p>
<p>A little over a year in, we received a notice from Slack showing we had reached our maximum file upload quota. We knew a file upload limit existed, but we had blown past it months earlier with nothing changing. We sprung into action to bring it down applying manual and automatic deletion tools. After a week of work, we discovered that files uploaded to private channels could not be removed, even if the channel and users were absent. This meant our ability to solve the problem was inhibited. After consulting Slack Support, no dice.</p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/slack-is-destroying-communities/d55a17865fe0d666.png" alt="Sunday, July 24, 2016"></p>
<p>We took a direct approach and launched a campaign where we emailed our massive user list and asked that they clear their files inside private channels. If they did, we would mail them a sticker with the community logo and a thank you a letter. It was fun for the community; they felt rewarded, and we saw action. However, the results were minimal and fleeting. Most of the files remained in limbo untouched.</p>
<p>It hobbled us, but we were alive. As things go, it wasn’t long before our next catastrophe landed. Within Slack’s platform, everything is persistent and permanent. If a user is inactive or disabled, their history and files remain indefinitely. This led to us reaching another maximum. Slack had been calculating the total number of messages users had made, which applied against a limit. One morning, they met us with a message that recommended we upgrade to increase the message limit, which we couldn’t do. The result was a rolling total that, when reached, would clear (or hide) previous messages creating a kind of impermanence for all of our data.</p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/slack-is-destroying-communities/5c2caa9b0434050c.png" alt=""></p>
<p>We officially had to choose between living on the free tier or attempting to raise tens of thousands of dollars annually from both our active and inactive users for a free community.</p>
<h2>The proud owners of inaccessible bits</h2>
<p>After the mediocre result of the file deletion campaign, it was clear we would need to limp along. Messages would disappear every day and users would complain but ultimately remained active. Photos and screenshots would error, and they would let it go. We provided notifications but effectively, our community became a kind of crappy Snapchat.</p>
<p>It didn’t take long before we heard users, specifically women, didn’t feel safe engaging with the community. They wanted to talk about code, but stayed within private channels so they could avoid slimy individuals direct messaging them. We sought a way to allow members to block or ban other users but found nothing. Slack didn’t provide help, and at the time these tools didn’t exist. All we could do was field the issue as admins and disable the offending users. There wasn’t a method to protect victimized users.</p>
<p>These issues along with the rise of the <a href="https://en.wikipedia.org/wiki/Pepe_the_Frog">Pepe memes</a>, trolling, and bullshit in public channels left us discouraged. We wrote content policies and began aggressive policing, but it pissed off users that were reasonable and emboldened those that were not. We created channels that would allow freedom of speech, however, this led to lawless (obviously) channels that caused little groups to spin off. Each as heinous as their parent.</p>
<p>As admins, we concluded this vessel was on a collision course. We spoke ad nauseam about how it was a stain on the web development community and how, at some point, it needed to be destroyed. With the right tools we could patch the holes, but Slack was on their mission to improve collaboration within businesses. Rightfully, communities didn’t fit within that model.</p>
<h2>Like trying to get water from a well you know is dry</h2>
<p>The Frontend Developers community was done. As creators, we knew it was unreasonable to subject users to a toxic environment, especially if they are at risk or unhappy. Having already tried several platforms; without comparable options, we chose to destroy the community.</p>
<p>Days later, I received a message from the <a href="https://craftcms.com/blog/discord">Craft CMS</a> team. Another enormous community on Slack.</p>
<blockquote>
<p>We’re emailing you because you had an account on Craft Slack. We thought you’d like to know that as of today, the Craft CMS community has a new home on <a href="https://lists.pixelandtonic.com/t/r-l-jthlzdy-utduiijtdy-r/">Discord</a>. … the TL;DR is that Slack isn’t built for communities, and Discord is.</p>
</blockquote>
<p>I logged in and found that these communities were <strong>vibrant</strong>. It was like Slack but had everything we needed. Originally built for the gaming community, it had created tools that dealt with community behaviors we had experienced. The ability to ban, kick, and warn bad apples, free screen sharing, no file or message limit, content moderation, and much more.</p>
<h2>Everything except the freedom to cross-office firewalls</h2>
<p>We had an answer. An hour after receiving the email I shared my plan with the admin team and wrote the final message. This was Tuesday, and we would move by Friday. In our mind, this was an all-or-nothing situation and given how handicapped our community was, we naively thought members would love the idea.</p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/slack-is-destroying-communities/812de367c26a164e.png" alt=""></p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/slack-is-destroying-communities/42eaa20277c888ff.png" alt=""></p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/slack-is-destroying-communities/c757f65833f3fe96.png" alt=""></p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/slack-is-destroying-communities/399e4b57b63e2594.png" alt=""></p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/slack-is-destroying-communities/476b792b46f37dca.png" alt=""></p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/slack-is-destroying-communities/6df13be349aadb65.png" alt=""></p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/slack-is-destroying-communities/6de8663c92c63835.png" alt=""></p>
<h2>This smoking radioactive hole is my place of peace</h2>
<p>There were a lot of angry users. This was <strong>their community</strong> — flaws and all. We assumed we took an insignificant part of that day; forgetting how valuable the relationship between work and community was. They love Slack because it’s part of their work-day life; our connection with the platform was parasitic not symbiotic.</p>
<p>Despite our realization, we had already loaded up the truck and packed grandma. There was no turning back. Four years in, Slack hadn’t seen the value and with the impending IPO, it was unlikely they would break new ground. <strong>The community was finished with their platform.</strong></p>
<p>Friday the 15th was our last day on Slack. Over our 1500 days on there, we’ve received 26,435 requests to join; 17,301 of those became members. Of those, only 266 members has deactivated their account.</p>
<p><img src="https://iqscb8r7qx1brxma.public.blob.vercel-storage.com/media/articles/slack-is-destroying-communities/c8c2046257bfb052.png" alt=""></p>
<p>Come check out our new home on Discord <a href="https://discord.gg/aBx8dcu">https://discord.gg/aBx8dcu</a>.</p>
<p><em>Without the incredible volunteers that spend (and have spent) their time working to provide Web Developers a place to connect, none of this is possible. From the bottom of our hearts, the community and I, thank you.</em></p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/slack-is-destroying-communities">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>Live by the EpiPen, die by the EpiPen</title>
      <link>https://zachshallbetter.com/writing/live-by-the-epipen-die-by-the-epipen</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/live-by-the-epipen-die-by-the-epipen</guid>
      <pubDate>Sat, 27 Aug 2016 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>I wish I had a photo of Saturday to share with the world. A snapshot of what it’s like for a person who rides an extreme line when it comes…</description>
      <content:encoded><![CDATA[<p>I wish I had a photo of Saturday to share with the world. A snapshot of what it’s like for a person who rides an extreme line when it comes to health. A view of my nightstand scattered with medications, tissues, and a blood-filled EpiPen. An upset preteen calling 911 and the other dragging my body down stairs. The chaos left behind after struggling for my life.</p>
<p>I’m habitually victimized by my own immune system. Dust, smoke, pets, grass, trees, and a page full of food allergies. Generally it’s just mild irritation or wheezing, but sometimes it breaks into <a href="http://www.mayoclinic.org/diseases-conditions/anaphylaxis/basics/definition/con-20014324">Anaphylaxis</a> and respiratory distress. A tightness that can only be compared to drowning while having a heart attack.</p>
<p>This is purgatory and countless individuals, diagnosed or not, suffer day-to-day with it. We have few instant resources to save ourselves, but they do exist. Tried-and-true safeguards invented in the 70’s that behave like adrenaline to push our bodies into overdrive. They give us enough time to seek help. The king of these at the moment, is the <a href="https://www.epipen.com/">EpiPen</a>.</p>
<blockquote>
<p>Up to <a href="https://www.foodallergy.org/facts-and-stats">15 million Americans have food allergies</a>. Affecting 1 in every 13 children, or 8% of the population. <a href="http://www.aaaai.org/about-aaaai/newsroom/asthma-statistics">25 million Americans had asthma in 2009</a> up 5 million since 2001.</p>
</blockquote>
<p>EpiPens expire. And once a year you need to re-up. When it’s time, I’ll normally buy four for under a hundred dollars (after coupons and rebates). One for the home, office, car, and my wife’s purse. You forget about them because they’re designed to be safeguards — a small peace-of-mind for everyone around me. Now, since tagging myself on Saturday, I’m going to need to refill that prescription.</p>
<p>The price though has changed, and CEO Heather Bresch of <a href="https://www.google.com/#q=Mylan">Mylan</a>, the maker of the EpiPen, is telling us that the current $608 cost isn’t their fault. Claiming that the real culprit is the number of hands the product moves through and overbearing official bodies meddling in the process. Boasting instead of her company’s heroic work to pass legislation that puts their product in homes and schools around the world — saving millions.</p>
<p>I’d love to provide an expert opinion on the industry and governance wrapping this, but I can’t, and it doesn’t matter. What I can say, is that even if there is hyper overreach surrounding this product, massive cost overruns, and shortages, it doesn’t validate a price increase over a decade from $60 to $600, especially given this product was <a href="http://usuncut.com/class-war/epipen-taxpayer-money/">developed with taxpayer money</a> and has remained <a href="https://www.google.com/patents/US20040211806">unchanged</a>.</p>
<p>If Mylan is the altruistic company they say they are, striving heroically to save the planet, they simply cannot justify a 10x price increase on a rescue device. Especially, when nothing has changed and they’ve been the only game in town since the end of the Vietnam War. This is not how a protagonist behaves. If you’re a selfless hero, taking massive bonuses and increasing profits isn’t an intentional motion. It’s the reward you earn from a society that appreciates the work you’re doing.</p>
<blockquote>
<p>The adult EpiPen has 0.3mg of <a href="https://en.wikipedia.org/wiki/Epinephrine">epinephrine</a>. The cost of 1.0mg of epinephrine is around $2 dollars retail.</p>
</blockquote>
<p>Even with medications, health insurance, and systems in place I almost died. I was lucky because I had that support, but there are many people that are in worse positions. Parents required to buy duplicates for school, minimum wage workers, and those without insurance. They’re simply not going to miss paying rent because they need insurance medicine — despite how illogical that might sound.</p>
<blockquote>
<p>In 2012, <a href="http://opinionator.blogs.nytimes.com/2015/03/20/recycling-unused-medicines-to-save-money-and-lives/">studies indicate</a>, about one in four American adults, perhaps 50 million people, <a href="http://www.nytimes.com/interactive/2014/12/18/health/cost-of-health-care-poll.html">failed to fill a prescription</a> they needed because of the cost.</p>
</blockquote>
<p>What happens next, is that people like myself will die, product names will be changed, CEOs like Martin Shkreli will be fired, and feel-good laws will be forced through containing loopholes and earmarks. It’s not change, its meaningless social compliance.</p>
<p>It’s now time to acknowledge the behavioral trend of influential medical manufacturers. This issue isn’t about the Affordable Care Act, the government, or pharmacies. It’s about corporate greed and the abuse of power that allows those organizations to take every ounce of advantage. Removing that power and binding them to ethical codes is a top priority and would have a sweeping impact on medical costs across the board.</p>
<p>If you want to truly make a difference, start by telling your story to everyone. Don’t be scared, many of us are sick and want to relate. Then spend five minutes <a href="http://whoismyrepresentative.com/">calling your state representatives</a> and ask them to work on four specific issues. Any of which can have a huge impact. I’ve written a script that should help.</p>
<blockquote>
<p>Hello [representative],</p>
</blockquote>
<blockquote>
<p>I’m a concerned constituent. I believe the recent events regarding the EpiPen, Daraprim, and our pharmaceutical system are an example of a serious problem harming Americans health. I will support you and your campaign, if you work on these four solutions immediately. First, set a limit on out-of-pocket prescription costs. Second, push for a fast track approach for approval of critical generic versions of common drugs through the FDA. Third, set limits on the life cycle and allowed changes to pharmaceutical and medical device patents. Finally, allow limited importation of drugs from countries that have a regulatory system similar to that of the U.S to encourage competition.</p>
</blockquote>
<blockquote>
<p>Thank you for your time.</p>
</blockquote>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/live-by-the-epipen-die-by-the-epipen">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
    <item>
      <title>Dear Mailchimp,</title>
      <link>https://zachshallbetter.com/writing/dear-mailchimp</link>
      <guid isPermaLink="true">https://zachshallbetter.com/writing/dear-mailchimp</guid>
      <pubDate>Thu, 28 Apr 2016 00:00:00 GMT</pubDate>
      <dc:creator>Zach Shallbetter</dc:creator>
      <description>We love your service! You focused on UX and UI while your competitors focused on the enterprise. Building a user base with jokes and beauty…</description>
      <content:encoded><![CDATA[<p>We love your service! You focused on UX and UI while your competitors focused on the enterprise. Building a user base with jokes and beauty before it was cool. You won us, and we’ve since referred all of customers to your service. You deserved it.</p>
<p>Then you gave us Mandrill! Finally, allowing us to manage our client’s transactional emails without a lot of headaches. It took very little overhead and provided a balance between services we offered. When a client would ask, we’d say “it’s built by Mailchimp!” and they wouldn’t flinch at all. In most cases, it only handled a handful of emails a month, but it was perfect. It simply, quietly, supported a small part of a bigger monster.</p>
<p>That’s why your <a href="http://blog.mandrill.com/important-changes-to-mandrill.html">February announcement</a> has us reeling. Being developers ourselves, we understood the overhead needed to run a service and desire to focus on a single product. However, we also knew that many of our clients wouldn’t understand why this was awesome, leaving the cost to outweigh the benefit. Either way, we shared the details with them and presented solutions. Pay for the service indefinitely or move to something else that’s less expensive or free.</p>
<p>Being a great big company that builds great big things, you know how projects and web development cycles generally work. You diligently toil to get your gizmo off the ground and when satisfied, shift onto something else. Hopefully, only needing to return for enhancements and minor repairs. That’s what our company does for our clients. We build awesome things that don’t need a lot of maintenance.</p>
<p>When you decided to make this shift, you forced our company to halt and double-back on living breathing work. Requiring us to reconnect and update clients on systems that didn’t need to be touched. Leaving us to either shoulder the cost, or justify the expense for the client. All the while, being generally cold in your communication and not offering grandfather or alternatives to your pro account. It put us in a frustrating position and seemed an odd and dramatic change from the company we knew and loved.</p>
<p>So instead of sticking with you for the long haul and crossing our fingers, we‘ve decided to spend our time reconnecting with our clients and moving them elsewhere. We don’t dislike you, we just feel slighted and given the increasingly aggressive tone of your emails, I imagine we’re not alone.</p>
<p>These are scenarios that build competitors. We really enjoyed your service, but you chose to take an aggressive stance simply to onboard people into your pro service. While it may seem finicky, this modern world runs on relationships and you fumbled it.</p>
<p><em>Originally published at <a href="https://zachshallbetter.com/writing/dear-mailchimp">zachshallbetter.com</a>.</em></p>]]></content:encoded>
      
    </item>
  </channel>
</rss>