<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Hal on Medium]]></title>
        <description><![CDATA[Stories by Hal on Medium]]></description>
        <link>https://medium.com/@hal.is.writing?source=rss-9d7ee8daf241------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*jh8qDJ3SF7pT8qqQ</url>
            <title>Stories by Hal on Medium</title>
            <link>https://medium.com/@hal.is.writing?source=rss-9d7ee8daf241------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 04:19:32 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@hal.is.writing/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[The higher the floor, the less it holds]]></title>
            <link>https://uxplanet.org/the-higher-the-floor-the-less-it-holds-20091991ef29?source=rss-9d7ee8daf241------2</link>
            <guid isPermaLink="false">https://medium.com/p/20091991ef29</guid>
            <category><![CDATA[information-architecture]]></category>
            <category><![CDATA[cognitive-load]]></category>
            <category><![CDATA[design-principles]]></category>
            <category><![CDATA[product-design]]></category>
            <category><![CDATA[ux-design]]></category>
            <dc:creator><![CDATA[Hal]]></dc:creator>
            <pubDate>Tue, 01 Sep 2026 19:56:01 GMT</pubDate>
            <atom:updated>2026-09-01T19:56:01.046Z</atom:updated>
            <content:encoded><![CDATA[<p>A way of designing screens where information gets less dense, and navigation gets quieter, the further up you go.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XIEciMxb2wf2gOSMkyoXWA.png" /></figure><p>Every screen has floors. We don’t usually say it out loud, but we feel it. Some information sits on the ground, foundational, the place you keep returning to. Some belongs upstairs, out of the way until you reach for it. And some floats above everything, a quick alert you glance at and forget.</p><p>For a long time I treated information hierarchy as a styling job. Bigger here, dimmer there, more contrast on the thing that matters. A few years ago I started treating it as a spatial one instead, and gave it a single rule: the higher you go, the less information and the less navigation each floor carries.</p><p>That rule changed how the whole system felt to use.</p><h3><strong>The ground floor</strong></h3><p>This is where people live. In a building it’s the lobby, the shop floor, the kitchen. In an app it’s no different.</p><p>The ground floor gets the full screen. Primary tasks, multiple things happening at once, navigation back and forth. It’s the place you return to between everything else, so it earns the most room and most of your design thinking.</p><p>Getting this floor right is about generosity. Give it space. Don’t crowd it with things that belong upstairs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*q7rEuhabfwLsTJNWMdXVzw.png" /></figure><h3><strong>The first floor</strong></h3><p>The first floor is quieter. You go up there for one reason and you do one thing.</p><p>I think of it as offloading. When a ground floor interaction starts to accumulate secondary detail, you send that detail up. The first floor handles it in a single, focused task. It can still use the full screen, but it holds only what’s needed, and navigation goes one way: back down.</p><p>There’s something clarifying about that constraint. Whenever I found myself wanting to link sideways between first floor screens, it was almost always a sign I’d sent something up there that belonged on the ground. The floors become diagnostic. The structure tells you when you’ve put something in the wrong place.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KpaA1_gVa4DlXnAipEYY4w.png" /></figure><h3>The second floor</h3><p>This is where I had to resist the urge to do too much.</p><p>The second floor is for high-level signals only. A status, a notification, a quick number. It takes up roughly a fifth of the screen. It doesn’t navigate and it doesn’t ask anything of you. It tells you something and closes, returning you to where you were.</p><p>I kept wanting to add a button. A link. Just one tap to act from here. Every time I did, I was collapsing the floor, asking the second to do the work of the first. The constraint is the whole point.</p><p>The research under the rule</p><p>This isn’t only a feeling. Two well-documented principles sit underneath it.</p><p>The first is Hick’s Law: the time it takes to make a decision grows with the number and complexity of the choices in front of you. That’s the navigation half of the rule. Fewer ways to move on the upper floors means fewer decisions, so the higher you climb, the less there is to weigh up.</p><p>The second is cognitive load: the mental effort it takes to understand and use an interface. Every element a person has to process costs something, whether they act on it or not. Thinning the information as you go up isn’t decoration. It’s how you keep the upper floors from quietly taxing someone who only came up to check one thing.</p><p>Neither idea is mine. Jon Yablonski has a clear write-up of both at lawsofux.com, and Nielsen Norman Group has written for years about reducing cognitive load. The floors are just a way to put those principles somewhere you can stand.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WBO88j4WOjMSQPwxvGhAAQ.png" /></figure><h3>Practical approaches</h3><p>You can apply these approaches to help map out and use the different floors for your work.</p><h3>Why floors work</h3><p>What surprised me was how much people relaxed once the floors were consistent.</p><p>I think it comes down to orientation. When everything can be anywhere, you stay slightly braced, scanning, deciding where to look. When the system has a clear vertical logic, you build a kind of spatial memory for it. You know roughly where you are and what this height of the building is allowed to do. You stop thinking about where to look, and you didn’t have to be told.</p><p>The floors don’t make a screen simpler. There’s the same amount of work to do. What they do is make it legible, so attention has somewhere to rest and somewhere to go.</p><p>I’m still sitting with how far the metaphor stretches. Whether it holds on small screens, whether it scales to dense, data-heavy tools, whether all interfaces are navigated spatially even when we pretend they aren’t. But every time I get the floors right, the same thing happens. The product stops feeling busy, and starts feeling like a building someone already knows their way around.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=20091991ef29" width="1" height="1" alt=""><hr><p><a href="https://uxplanet.org/the-higher-the-floor-the-less-it-holds-20091991ef29">The higher the floor, the less it holds</a> was originally published in <a href="https://uxplanet.org/">UX Planet</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The map underneath the code]]></title>
            <link>https://medium.com/design-bootcamp/the-map-underneath-the-code-5c9640041111?source=rss-9d7ee8daf241------2</link>
            <guid isPermaLink="false">https://medium.com/p/5c9640041111</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[documentation]]></category>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[cursor-ide]]></category>
            <dc:creator><![CDATA[Hal]]></dc:creator>
            <pubDate>Thu, 13 Aug 2026 21:31:01 GMT</pubDate>
            <atom:updated>2026-08-17T21:15:14.632Z</atom:updated>
            <content:encoded><![CDATA[<p>What happens when AI can explain the code it just wrote, not only write it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7-FdAhOHmpJlhDKRoh1R1w.png" /></figure><p>There is a moment, after something finally works, when I realise I can no longer fully explain it. The feature runs. The buttons do what they should. But if you sat me at a whiteboard and asked me to draw how it all fits together, I would hesitate. The thing exists, and somehow it has already outgrown my memory of it.</p><p>This happens more now than it used to. I build faster than I did a year ago, because AI writes a lot of the code with me. That part is real and I lean on it every day. But speed has a quiet side effect. You can arrive at a working system you never fully held in your head.</p><h3>Working is not the same as understood</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Pqxb1RpNrKlQqLTGmM00gg.png" /></figure><p>A diff is a strange thing to rely on. It tells you what changed, line by line, but it says almost nothing about how the system behaves. You can read every function in a file and still not see the shape of it. What calls what. Where the data flows. Which step quietly runs in the background. What happens when one piece fails.</p><p>Code is precise and almost illegible at the same time. It is the most accurate description of a system that exists, and also the hardest one to reason about out loud. That gap, between something being correct and something being understandable, is where most of the confusion in a team actually lives.</p><p>For years the only way to close that gap was slow. Someone senior would sit down for an afternoon, trace the code by hand, and turn it into a diagram. By the time they finished, the code had usually moved on, and the diagram was already a little untrue.</p><h3>Asking the code to explain itself</h3><p>A while ago I started doing something simple. After the agent built a feature, I asked it to explain the feature back to me. Not as more code. As a map.</p><p>I pointed it at one file, a set of Next.js server actions sitting behind a submission detail page, and asked it to draw the architecture from what was actually there. What came back was not a summary. It was a document I could read in a minute and trust.</p><p>A high-level flow, drawn in plain boxes, from the client component down through the server action and out to the database. A section on security that made the quiet decisions loud: which queries ran under the user’s session and row-level security, which ran with elevated service-role access, where the service key must never travel. A data flow for each action, step by step. The early exit paths, drawn as a small decision tree. An error handling table that listed every failure point and what the user would see at each one.</p><p>None of that was new information. It was all in the code already. But I had never seen it in one place, in language I could hold.</p><h3>What the map showed</h3><p>The interesting part is what becomes visible once the shape is on the page.</p><pre>High-Level Flow<br><br>┌─────────────────────────────────────────────────────────────────┐<br>│              Client Component (check-again-dialog.tsx)          │<br>│  • User confirms &quot;Check again&quot; in global confirm dialog         │<br>│  • Calls checkAgainSubmission(submission_id)                    │<br>└─────────────────┬───────────────────────────────────────────────┘<br>                  │<br>                  ▼<br>┌─────────────────────────────────────────────────────────────────┐<br>│                    actions.ts (&#39;use server&#39;)                    │<br>│  • createServer() — SSR Supabase client (user session + RLS)    │<br>│  • deleteSubmission — hard-delete owned row                     │<br>│  • checkAgainSubmission — clone row + allowance + side effects  │<br>└─────────────────┬───────────────────────────────────────────────┘<br>                  │<br>        ┌─────────┴─────────┐<br>        ▼                   ▼<br>┌───────────────────┐ ┌───────────────────────────────────────────┐<br>│  User-scoped      │ │  Service-role query helpers                │<br>│  PostgREST (RLS)  │ │  • checkSubmissionAllowance (RPC)          │<br>│  submissions      │ │  • insertResubmission                      │<br>│  delete / select  │ │  • addTimelineEntryServiceRole             │<br>└───────────────────┘ │  • notifyAdminsNewSubmission               │<br>                      │  • notifyUserSubmissionConfirmed           │<br>                      └───────────────────────────────────────────┘<br>                  │<br>                  ▼<br>┌─────────────────────────────────────────────────────────────────┐<br>│              revalidatePath(&quot;/user/submissions&quot;)                │<br>│  • Refreshes submissions list cache after mutation              │<br>└─────────────────────────────────────────────────────────────────┘</pre><p>Reading the map, I could see things that were invisible while scrolling through functions. Side effects that fire and forget, so a failed notification never rolls back the main write. A monthly allowance check sitting as a gate before anything gets created. A race condition where two requests pass the same gate and a database trigger has to catch the second one. You do not notice these things in a stream of code. You notice them when the flow is drawn.</p><p>The code already knew all of this. The map was just how it finally said it to me.</p><h3>A thing other people can stand in front of</h3><p>Then I asked for one more step. Turn the map into a board the team can open and edit.</p><p>The same process now generates a FigJam diagram from the document, links it back into the markdown, and leaves you with something a designer, a new engineer, or a product manager can move around together. Not a screenshot that goes stale. A living picture of how the thing works, drawn from the code as it actually is. You can open one of these boards here: <a href="https://www.figma.com/board/dzA7QebkACODLNPK0n8P5u/Submission-detail-server-actions?t=11x8YagyPvc8LgmT-6">figma.com/board/dzA7QebkACODLNPK0n8P5u</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hnbGvZk6M5bp25LAQzCnnQ.png" /></figure><p>I keep coming back to a prototype I built years ago for Transport for London. What changed the room was not my argument. It was that people could stand in front of something real instead of imagining it from a slide. A good architecture map does a smaller version of the same thing. It moves a system out of one person’s head and onto a surface everyone can point at.</p><h3>When legibility gets cheap</h3><p>What stays with me is not the diagram. It is how short the path has become.</p><p>Producing a clear, accurate map of a system used to be expensive enough that we mostly didn’t do it. We let the understanding live in one or two people and hoped they stayed. Now the cost of drawing that map has dropped close to zero, and it comes straight from the code rather than from someone’s fading memory of it.</p><p>I think that quietly changes things. A team can bring someone new up to speed in an afternoon. A designer can finally see the system they are designing for. A group can argue about the right thing, because the shape is on the screen instead of trapped in a single mind.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WrNATzTF3htrwuAWq4SgYQ.png" /></figure><p>I turned this into a small Cursor skill called /arch-flow. Point it at a file and it reads the code and draws the map. Ask, and it turns that map into a FigJam board you can share. It is free and open source: <a href="https://github.com/hferello/ai/tree/main/arch-flow">github.com/hferello/ai/tree/main/arch-flow</a>.</p><p>What I find valuable about AI is not only that it writes the code with me. It writes the code, and it can turn around and explain that code back, clearly enough that other people understand it too. I’m still working out how far that second thing goes. But every time I open one of these maps and see the shape of something I built and couldn’t quite hold, it feels like progress.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5c9640041111" width="1" height="1" alt=""><hr><p><a href="https://medium.com/design-bootcamp/the-map-underneath-the-code-5c9640041111">The map underneath the code</a> was originally published in <a href="https://medium.com/design-bootcamp">Bootcamp</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Your AI Agent Has Amnesia. Here’s the Fix.]]></title>
            <link>https://medium.com/@hal.is.writing/your-ai-agent-has-amnesia-heres-the-fix-1b00bb6880b2?source=rss-9d7ee8daf241------2</link>
            <guid isPermaLink="false">https://medium.com/p/1b00bb6880b2</guid>
            <category><![CDATA[cursor-ide]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Hal]]></dc:creator>
            <pubDate>Thu, 16 Jul 2026 10:06:02 GMT</pubDate>
            <atom:updated>2026-07-16T10:06:02.429Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DBhKGB38FqAsazT9jPEhag.png" /></figure><p>I love AI coding agents. I use them constantly. But there’s a problem nobody talks about enough.</p><p>They forget what you’re building.</p><p>Every new chat, every new session — the slate is blank. Your agent doesn’t know the product. It doesn’t know the boundaries. It doesn’t know what you’ve already decided.</p><p>So you repeat yourself. Again. And again.</p><p>Or worse — you don’t. And the agent confidently builds the wrong thing.</p><p>I got tired of that. So I built a fix.</p><h3>Smart tools. Zero memory.</h3><p>Here’s what happens without product context.</p><p>You ask an agent to add a feature. It does. But it also adds three things you never asked for. It picks a library you’d never use. It ignores a constraint you forgot to mention.</p><p>The agent isn’t dumb. It’s uninformed.</p><p>It’s like hiring a brilliant contractor but never handing them the blueprint. They’ll build <em>something</em>. It just won’t be what you wanted.</p><h3>One file. Bunch of questions.</h3><p>I built a Cursor skill called /context. It writes a single file — docs/context.md — that gives every AI agent in your project the context it needs.</p><p>No setup wizards. No complex configs. Just a conversation.</p><p>Type /context and the agent walks you through bunch of questions. One at a time.</p><p>After each answer, the file updates on disk. If your session crashes halfway through, just run /context again. It picks up where you left off.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*E2y06IqAI7UtcNNZi39e6A.gif" /></figure><h3>Not sure? Say “you tell me.”</h3><p>This is my favourite part.</p><p>Don’t know the answer to a question? Just say “you tell me.” The agent researches your codebase and proposes an answer. You confirm it, tweak it, or reject it.</p><p>Don’t care about a question? Say “skip.” That section won’t appear in the doc at all.</p><p>No filler. No fluff. No guessing.</p><h3>It pushes back. On purpose.</h3><p>I didn’t want a polite transcription bot. I wanted a thinking partner.</p><p>List ten must-haves and it says: <em>“That’s ten. Pick three you’d ship without the others.”</em></p><p>Give a vague pitch and it says: <em>“I can’t picture it yet — give me a concrete example.”</em></p><p>Describe a feature instead of an outcome and it says: <em>“That’s something it does — but what does the user actually get?”</em></p><p>This isn’t rudeness. It’s rigour. A tight context doc is worth ten sloppy ones.</p><h3>The red team</h3><p>After all nine questions, the skill does something unexpected. It turns on you.</p><p>Not maliciously. Constructively.</p><p>It re-reads the whole document as a critic. It checks for contradictions, hidden complexity, and scope creep. Then it goes deeper — challenging assumptions and suggesting simpler alternatives.</p><p>Things like: <em>“Is this must-have actually three features in a trenchcoat?”</em></p><p>Or: <em>“You’re anchored on one approach. Have you considered this instead?”</em></p><p>Clear issues get fixed on the spot. Judgment calls come back to you as questions. It’s the week-two realisation — compressed into five minutes.</p><h3>What the output looks like</h3><p>Here’s a real example from a receipt-tracking app for freelancers:</p><pre># Product Context</pre><pre>&gt; **One-liner:** Snap a receipt, auto-categorise the deduction,<br>&gt; export at tax time.</pre><pre>## Mission<br>Help solo freelancers stop losing track of expenses<br>so tax time isn&#39;t a scramble.</pre><pre>## Must-Haves<br>1. Snap/upload receipt → auto-extract vendor, amount, date<br>2. Assign a tax category (meals, travel, supplies, etc.)<br>3. Export year-end summary as CSV</pre><pre>## Out of Scope<br>- Invoicing or billing<br>- Multi-user / team accounts<br>- Tax filing or tax advice</pre><pre>## Success Criteria<br>- Receipt-in-hand to expense-logged in under 10 seconds<br>- 80%+ OCR extractions need zero correction<br>- One freelancer uses it a full quarter<br>  without reverting to spreadsheets</pre><p>Short. Specific. Actionable. Every section is something an agent can actually use to make better decisions.</p><h3>The rule that ties it together</h3><p>The context doc is half the system. The other half is a project rule.</p><p>You install a small .cursor/rules/context.mdc file into each repo. It tells every agent: read docs/context.md before doing anything significant.</p><p>Three things follow from that. Agents ship must-haves and push back on out-of-scope requests. If your request contradicts the doc, the agent flags it: <em>“The context doc says X. You’re asking for Y. Which wins?”</em> And if there’s no context doc and the work is big, it suggests running /context first.</p><p>The rule lives in the repo, not in your global config. It travels with the code. Everyone on the team gets the same guardrails.</p><h3>Install it in 30 seconds</h3><p><strong>Install the skill</strong> (once per machine). Open a terminal in Cursor and run:</p><pre>git clone --depth 1 https://github.com/hferello/ai.git /tmp/cursor-skill \<br>  &amp;&amp; bash /tmp/cursor-skill/context/install.sh \<br>  &amp;&amp; rm -rf /tmp/cursor-skill</pre><p>Restart Cursor.</p><p><strong>Install the project rule</strong> (once per repo). From your project, run:</p><pre>bash /path/to/context/install-project-rule.sh .</pre><p>Commit .cursor/rules/context.mdc so the whole team gets it.</p><p>Then open Agent chat, type /context, and start answering.</p><h3>Why this matters</h3><p>AI agents can build almost anything now. The catch: they still don’t know <em>what</em> they’re building unless you tell them. Every. Single. Time.</p><p>That’s the gap /context fills.</p><p>One conversation. One file. Every agent in every session stays aligned.</p><p>No more repeating yourself. No more rogue features. No more “wait, that’s not what I wanted.”</p><p>Just clarity. In five minutes.</p><p><em>The skill is open source. Grab it, try it, break it, make it better.</em></p><p><strong>GitHub:</strong> <a href="https://github.com/hferello/ai">github.com/hferello/ai</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1b00bb6880b2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Designing for the Wrong User]]></title>
            <link>https://uxplanet.org/designing-for-the-wrong-user-33178f5cb5b8?source=rss-9d7ee8daf241------2</link>
            <guid isPermaLink="false">https://medium.com/p/33178f5cb5b8</guid>
            <category><![CDATA[design-thinking]]></category>
            <category><![CDATA[cognitive-science]]></category>
            <category><![CDATA[psychology]]></category>
            <category><![CDATA[product-design]]></category>
            <category><![CDATA[ux]]></category>
            <dc:creator><![CDATA[Hal]]></dc:creator>
            <pubDate>Thu, 25 Jun 2026 06:54:15 GMT</pubDate>
            <atom:updated>2026-06-28T14:44:04.938Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dAVFGMaJf6EMe9UFoQ4qGA.png" /></figure><p>There’s a moment in an emergency when the world narrows.</p><p>Not metaphorically. Literally. Your peripheral vision contracts. Sounds flatten into background noise. The only thing that exists is the thing directly in front of you. Psychologists call it perceptual narrowing. The psychologist [J. A. Easterbrook described the mechanism back in 1959](https://doi.org/10.1037/h0047707): as emotional arousal rises, the range of cues we can take in shrinks. Your brain, under threat, stops processing what it deems unnecessary and concentrates everything on survival.</p><p>I think about this a lot when I’m designing screens.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EZqXSTC_GLTcALycadQWjw.png" /></figure><h3><strong>f22 — everything in focus</strong></h3><p>A camera lens at f22 keeps everything in focus. The foreground, the background, the blurry figure at the edge of the frame. Every element competing equally for your attention.</p><p>Most apps are designed at f22.</p><blockquote><em>Hence a wealth of information creates a poverty of attention<br> — </em><a href="https://gwern.net/doc/design/1971-simon.pdf"><em>Herbert Simon, 1971</em></a></blockquote><p>Every button visible. Every option available. Every notification badge clamouring for a glance. There’s a kind of democratic logic to it, an idea that giving users everything means giving them control. But control and <a href="https://www.nngroup.com/articles/minimize-cognitive-load/">cognitive load</a> aren’t the same thing. One is a feeling. The other is a measurable weight.</p><p>When I worked on an Australian Police Service app, we were designing for over 11k officers across a state the size of Western Europe. The brief was straightforward: make them more efficient. But the deeper we went into the research, the more the real question came into focus.</p><p>What does it cost someone to use a bad interface at the wrong moment?</p><h3><strong>Two officers, one screen</strong></h3><p>We did field research. Clipboards in hand, watching officers work. Not in a lab, but in the actual conditions of their days.</p><p>What became obvious quickly was that the same officer, the same person, the same hands and eyes and brain, was a different user depending on where they stood. At a desk finishing a report, they were calm, methodical, patient with complexity. In the field, mid-incident, moving or in a vehicle, their stress was elevated and their tolerance for visual noise had collapsed.</p><p>The interface didn’t know any of this. It presented itself the same way regardless.</p><p>This felt like a design failure. Not a feature gap. A philosophical one.</p><h3><strong>f2.8 — the aperture shifts</strong></h3><p>A camera at f2.8 does something beautiful and strange. It pulls one thing into sharp relief and lets everything else dissolve. The background doesn’t disappear, it just stops asking for your attention.</p><blockquote><em>It implies withdrawal from some things in order to deal effectively with others.<br> — </em><a href="http://www.yorku.ca/pclassic/James/Principles/prin11.htm"><em>William James, The Principles of Psychology, 1890</em></a></blockquote><p>We built this into the UX stress model. As an officer’s stress increased, the interface contracted. Non-essential elements receded. Choices narrowed. The screen stopped being a dashboard and started being a torch.</p><p>The metaphor came from photography but the logic is neurological. When the brain is under load, every additional decision has a cost. <a href="https://lawsofux.com/hicks-law/">Hick’s Law</a> tells us that the time to make a decision increases with the number of options. But that’s in a neutral state. Under stress, the relationship isn’t linear. It compounds. The <a href="https://en.wikipedia.org/wiki/Yerkes-Dodson_law">Yerkes-Dodson law</a>, first described in 1908, gives that curve its shape: performance climbs with arousal up to a point, then falls away, and the more complex the task, the sooner the fall begins.</p><p><a href="https://lawsofux.com/millers-law/">George Miller wrote in 1956</a> that the human mind can hold roughly seven items in working memory, plus or minus two. That was in a quiet room with a willing participant and no stakes. Put a person in a car responding to a call and that number shrinks considerably. A <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC5003767/">2016 meta-analysis of acute stress and executive function</a> found the same thing in the lab: across fifty-one studies, stress reliably impaired working memory.</p><p><a href="https://jnd.org/emotion-design-attractive-things-work-better/">Don Norman</a> has spent a career making the same point from the design side. Negative affect “focuses the mind,” he writes, and under threat that focus collapses into “narrow, tunnel vision.” His conclusion for anyone building tools for those moments is blunt: they “are best served by designs that emphasise function and minimise irrelevancies.” A torch, not a dashboard.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*r8IOCva-gRWDt0gm4QaChA.png" /></figure><h3><strong>What we don’t design for</strong></h3><p>Here’s what bothers me, the thing I keep coming back to.</p><p>Most UX design is optimised for a calm user. The personas we build, the testing we run, the environments we simulate. Someone seated, unhurried, with full cognitive resources available.</p><p>We design the f22 version of an interface and then we wonder why it breaks down under pressure.</p><p>Stress isn’t an edge case. It’s a condition of use. A parent navigating a hospital app with a sick child in their arms. A driver trying to follow directions in an unfamiliar city at night. A person rereading the same sentence in a financial document because they’re scared of what it says.</p><p>These aren’t unusual users. They’re all of us, on a bad day, when the stakes are real.</p><h3>Practical methods to shift between different stresses</h3><p>Stopping down the aperture comes down to a handful of concrete moves, each one a different degree of pulling something out of focus.</p><p><strong>1. Desaturate the unimportant:</strong> Drain the colour from elements that aren’t central to the task, so the eye has less to catch on as it scans the interface.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Z8FIax6X3FPZS1LQRt0NDw.png" /></figure><p><strong>2.</strong> <strong>Reduce the opacity of the secondary:</strong> Fade back elements that support the task without driving it, so they settle a layer beneath the thing in focus. Present enough to find, quiet enough to ignore.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OFxzCqOWEBvccKUQaY3yZA.png" /></figure><p><strong>3. Remove the nice-to-have entirely:</strong> Anything that lives in the optional category can go when stress is high. The most reliable way to lower cognitive load is to have less on the screen in the first place.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SjvlrlLsSlnZk2GyWuJYCw.png" /></figure><p><strong>4. Blur what falls outside the task:</strong> Let elements that don’t belong to the current workflow soften into the background. They still exist, they just stop asking for attention.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SwwARCxY_JCJTJ7eUEet6Q.png" /></figure><p><strong>5. Move into its own layer:</strong> A modal or a separate screen takes a secondary task out of sight, so the user can stay with the one that matters. A full-screen step usually beats a partial one, because it removes the surrounding noise instead of competing with it. The only context worth preserving is the kind that isn’t obvious, like where a deep link dropped someone.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uFu5fLCpSCMfwgoDA0BBqA.png" /></figure><p><strong>6. Shift things visibly, with motion:</strong> When you move an element elsewhere, animate the change so the user sees it hasn’t vanished, only relocated, and can be reached again when they need it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SHBIkv5ngwpHn378tH9lsg.gif" /></figure><h3><strong>What the camera knows</strong></h3><p>A photographer chooses their aperture deliberately. Wide open for intimacy. Stopped down for clarity. The choice shapes what the viewer sees and what they’re allowed to let go.</p><p>We don’t talk much about interface design in those terms. About what we’re choosing to keep in focus and what we’re allowing to blur. About the responsibility that comes with putting something in front of a person who is already carrying more than they can hold.</p><p>I’m not sure we’ve fully reckoned with that yet. The tools exist. The research is there. Miller, Kahneman, the whole field of cognitive load theory stretching back decades.</p><p>Something else is missing. An acknowledgement, maybe, that the person holding the screen is not always fine.</p><p>That sometimes they’re at f2.8 whether we planned for it or not.</p><h3><strong>References</strong></h3><p>Perceptual narrowing under arousal. Easterbrook, J. A. (1959). The effect of emotion on cue utilisation and the organization of behaviour. <em>Psychological Review</em>, 66(3), 183–201. <a href="https://doi.org/10.1037/h0047707">https://doi.org/10.1037/h0047707</a></p><p>Attention as selective withdrawal. James, W. (1890). <em>The Principles of Psychology</em>, Vol. 1, Ch. 11, p. 404. <a href="http://www.yorku.ca/pclassic/James/Principles/prin11.htm">http://www.yorku.ca/pclassic/James/Principles/prin11.htm</a></p><p>The attention economy. Simon, H. A. (1971). Designing organizations for an information-rich world. In M. Greenberger (Ed.), <em>Computers, Communication, and the Public Interest</em> (pp. 37–72). Johns Hopkins Press.</p><p>Arousal and performance, the inverted-U. Yerkes, R. M., &amp; Dodson, J. D. (1908). The relation of strength of stimulus to rapidity of habit-formation. <em>Journal of Comparative Neurology and Psychology</em>, 18, 459–482. Overview: <a href="https://en.wikipedia.org/wiki/Yerkes-Dodson_law">https://en.wikipedia.org/wiki/Yerkes-Dodson_law</a></p><p>Decision time and the number of choices. Hick, W. E. (1952) and Hyman, R. (1953), together the Hick-Hyman Law. Plain-language summary: <a href="https://lawsofux.com/hicks-law/">https://lawsofux.com/hicks-law/</a></p><p>The limits of working memory. Miller, G. A. (1956). The Magical Number Seven, Plus or Minus Two. <em>Psychological Review</em>, 63(2), 81–97. Summary: <a href="https://lawsofux.com/millers-law/">https://lawsofux.com/millers-law/</a></p><p>Stress impairing working memory. Shields, G. S., Sazma, M. A., &amp; Yonelinas, A. P. (2016). The effects of acute stress on core executive functions: a meta-analysis and comparison with cortisol. <em>Neuroscience &amp; Biobehavioral Reviews</em>, 68, 651–668. <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC5003767/">https://pmc.ncbi.nlm.nih.gov/articles/PMC5003767/</a></p><p>Cognitive load. Sweller, J. (1988). Cognitive load during problem solving. <em>Cognitive Science</em>, 12(2), 257–285. For the design application: Nielsen Norman Group, “Minimize Cognitive Load to Maximize Usability.” <a href="https://www.nngroup.com/articles/minimize-cognitive-load/">https://www.nngroup.com/articles/minimize-cognitive-load/</a></p><p>Affect, focus, and tunnel vision. Norman, D. A. (2002). Emotion &amp; design: attractive things work better. <em>Interactions</em>, 9(4), 36–42. <a href="https://jnd.org/emotion-design-attractive-things-work-better/">https://jnd.org/emotion-design-attractive-things-work-better/</a></p><p>Attention as a finite resource. Kahneman, D. (1973). <em>Attention and Effort</em>. Prentice-Hall.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=33178f5cb5b8" width="1" height="1" alt=""><hr><p><a href="https://uxplanet.org/designing-for-the-wrong-user-33178f5cb5b8">Designing for the Wrong User</a> was originally published in <a href="https://uxplanet.org/">UX Planet</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why is the spacing 24px and not 20px?]]></title>
            <link>https://medium.com/@hal.is.writing/why-is-the-spacing-24-and-not-20-cc1cdf2e2757?source=rss-9d7ee8daf241------2</link>
            <guid isPermaLink="false">https://medium.com/p/cc1cdf2e2757</guid>
            <category><![CDATA[typographic]]></category>
            <category><![CDATA[mathematics]]></category>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[product-design]]></category>
            <category><![CDATA[golden-ratio]]></category>
            <dc:creator><![CDATA[Hal]]></dc:creator>
            <pubDate>Mon, 04 May 2026 23:01:02 GMT</pubDate>
            <atom:updated>2026-06-26T21:15:57.192Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Z0Zlfx5Lc2dPpgV4JZbA_A.png" /></figure><p>There’s a question I kept coming back to while designing. Not philosophically. Practically. When someone on the team asks why the spacing is 24 and not 20, what do you say?</p><p>“It felt right” is honest, but it doesn’t travel. It doesn’t survive a handoff, a new hire, a design system that has to outlast the person who made it.</p><p>I started building a number system to try to answer that question. Not for anyone else, at first. Just to see if I could make something where the answer was always there.</p><h3>The first was 8</h3><p>Before anything else, there was a base unit. 8.</p><p>It has practical advantages that are easy to explain. It multiplies cleanly. It scales perfectly across iOS and Android, including the edge cases like Android’s @0.75 and @1.5 displays. Icons built on an 8pt grid don’t break when the resolution changes.</p><p>It made sense to use this as the starting point for everything that followed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*P95clvrpp0-_nB7aW6guvA.png" /></figure><h3>Typographic ratios</h3><p>The first library was typographic. A number system built around the classical type scale, sizes that have been used in print, on screens, in every medium type has ever lived in.</p><p>What I noticed is that the sizes didn’t need justifying. They arrived already related to each other, the way notes in a musical scale are. There’s a prearranged harmony to them, accumulated over centuries of people working out what the eye finds natural.</p><p>Starting from a scale with that kind of history means you’re not making decisions from scratch. You’re inheriting hundreds of years of visual reasoning.</p><p>That felt worth understanding better.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pR5mqSx5Jjd8BVmgT8BNOQ.png" /></figure><h3>Single-root scaling</h3><p>The second library came from a different direction. I wanted to understand what it would look like if every value in a design system, spacing, typography, layout, was derived from a single root.</p><p>From the base of 8, each step in the scale is roughly 1.618 times the last. That ratio, φ, gave me a single multiplier to derive every value from one root. Whether the ratio itself matters less than I expected is part of what I’m still sitting with. What I was actually after wasn’t beauty by formula. It was traceability. Values that connect back to something, rather than values that connect back to nothing.</p><p>The number system gives you horizontal and vertical rhythms too. All text flows along a baseline derived from the same logic. The grid follows. Icons follow. Everything moves from the same root.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2VYl-hSooP14Rj0lTC5CIQ.png" /></figure><h3>Base 10</h3><p>The third library went the other direction entirely.</p><p>Base-10 spacing. Multiples of ten, with mid-steps for finer control. 10, 15, 20, 25, 30. Values that are easy to hold in your head and easier to apply consistently across a team.</p><p>There’s no Fibonacci here, no golden ratio. The logic is just legibility. Sometimes a designer needs to move quickly, or hand something off to someone who doesn’t want to think about ratios. Sometimes the math is just clarity.</p><p>It belongs in the same family as the others because it answers the same question. Where does this value come from? Here the answer is: somewhere everyone can follow.</p><h3>Colour was the missing piece</h3><p>Most design systems treat colour scales as a separate problem. You pick some percentages, you generate a palette, and you call it done. The logic that governs spacing doesn’t touch colour at all.</p><p>That disconnection bothered me more the longer I worked on it.</p><p>I wanted to know what happens when you apply the same proportional thinking to colour directly. HSB colour, specifically, hue, saturation, brightness, because it’s the model that maps most naturally to how we actually think about colour. Hue is the position on the colour wheel. Saturation is how much colour is injected into white. Brightness is how much the lightbulb is turned on. It’s intuitive in a way that RGB, which describes what a screen is doing, is not.</p><p>I started working through the idea in a conversation with Claude. At some point, the concept was fully formed in the exchange. The logic, the maths, the expected output. It just didn’t exist as anything I could point to yet.</p><p>So I asked it to turn the conversation into a working HTML page. Brought it into Cursor to finish the job. Pushed it to GitHub.</p><p>One sitting. From a thought I could only describe to people, to a tool with a URL anyone could open and use.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tldT1s0Y84afxG4-BlY9Kw.png" /></figure><h3>Names instead of numbers</h3><p>I didn’t stop at Figma. The same three token sets are available as an npm package. Install them, import a single CSS file, and the values are in your project.</p><p>The spacing scale uses names instead of numbers. gap-section, p-loose, m-apart. Because the relationship between elements matters more than the pixel value. The number follows from the ratio. The name follows from the intent.</p><p>Each library compiles into three files. Raw primitives. A semantic layer with dark mode. And responsive breakpoints that adjust type and grid automatically across desktop, tablet, and mobile. It works with Tailwind v4 or as plain CSS variables.</p><h3>The question that outlasts you</h3><p>The thing these libraries share isn’t a visual style or a set of rules. It’s a way of asking a question before you make a decision.</p><p>Where does this value come from?</p><p>What I’ve found, working through each one, is that the question gets easier to answer the more the values are connected. Not because you stop making judgement calls, you still do, but because the judgement calls are fewer and more considered.</p><p>The specific foundation matters less than I thought it would. Fibonacci, base-10, a classical type scale. What they share is that they’re all answerable. Someone new to the project can ask why the spacing is 24 and not 20, and the answer is there waiting for them. It doesn’t depend on the person who chose it still being in the room.</p><p>I’m still not sure whether full proportional consistency across a system produces something that actually feels better to use, or just satisfies a kind of theoretical tidiness. I haven’t resolved that yet. It’s part of why I keep building.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*Q71XUWyodmEQ-rBtdRZC4Q.gif" /><figcaption>Number system in use</figcaption></figure><p><strong>Grab them free from Figma Community:</strong></p><ul><li><a href="https://www.figma.com/community/file/1623741379920496772">Typographic ratio — Design library by Hal</a></li><li><a href="https://www.figma.com/community/file/1622704033026100548/golden-ratio-design-library-by-hal">Golden ratio — Design library by Hal</a></li><li><a href="https://www.figma.com/community/file/1624041179065472961/base-10-ratio-design-library-by-hal">Base-10 ratio — Design library by Hal</a></li></ul><p><strong>NPM package: <br></strong><a href="https://github.com/hferello/design-libraries-npm">https://github.com/hferello/design-libraries-npm</a></p><p><strong>Design library site:</strong><br><a href="https://hferello.github.io/design-libraries/">https://hferello.github.io/design-libraries/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cc1cdf2e2757" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Every gap is a sentence]]></title>
            <link>https://medium.com/@hal.is.writing/every-gap-is-a-sentence-0d3ca078c9c7?source=rss-9d7ee8daf241------2</link>
            <guid isPermaLink="false">https://medium.com/p/0d3ca078c9c7</guid>
            <category><![CDATA[product-design]]></category>
            <category><![CDATA[typography]]></category>
            <category><![CDATA[design]]></category>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[ux-design]]></category>
            <dc:creator><![CDATA[Hal]]></dc:creator>
            <pubDate>Mon, 20 Apr 2026 11:01:01 GMT</pubDate>
            <atom:updated>2026-04-20T11:01:01.394Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wejvCfdBoFPBDGIq3DOG8g.jpeg" /></figure><p>Most spacing scales start with a list. 4, 8, 16, 32. Or 10, 20, 30. Chosen because they divided cleanly, or because someone else used them, or because they just felt right. I’ve built plenty of those scales myself. They worked. But I could never quite explain why the gap was 24 and not 20.</p><p>“It looks balanced” is true. It’s also useless.</p><h3><strong>What I was actually describing</strong></h3><p>I’ve been building a set of design token libraries, each one grounded in a different proportional system. The idea is that every value in a design system should trace back to something, so when someone asks “why is the spacing 24 and not 20?” the answer is already there.</p><p>When I got to spacing, I assumed it would be the easy part. Each system produces a clean sequence with its own logic underneath. Plug in the formula, get the values, done.</p><p>What I found instead was that the numbers were almost beside the point.</p><p>Every spacing decision is a decision about relationship. When I place two elements flush against each other, I’m saying: <strong>these are one thing</strong>.</p><p>When I pull them apart by a small breath, I’m saying: <strong>these belong together, but they’re distinct</strong>.</p><p>Keep going and eventually the message changes completely. These exist in different contexts. These are unrelated. <strong>A large gap doesn’t just mean more space. It means something different.</strong></p><p>I kept adjusting values by a pixel or two, trying to get something to “feel right”, and what I was really doing was trying to get the sentence right. The gap was saying something, and I couldn’t rest until it matched what I meant.</p><p>I’d always had a sense for proximity. But it took building my own system to stop reaching for pixel values and start designing in relationships.</p><h3><strong>The scale built itself</strong></h3><p>Once I saw it that way, the spacing system stopped feeling like a list of numbers and started feeling like a vocabulary. Each step is a word with a meaning: <strong>flush, tightly paired, loose group but breathing room, new section, unrelated, structural separation.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LyMN1djJD_m6-CHGm6U6lA.png" /></figure><p>The sequence isn’t just about quantity. It’s about what you’re communicating at each level. And when you name it that way, the next value isn’t arbitrary. It follows from what you’re trying to say.</p><p>The numbers are still there, grounded in a proportional system so they scale consistently across devices and contexts. But they’re downstream of the meaning. Not the other way around.</p><h3><strong>The question underneath the question</strong></h3><p>I’ve been thinking about why this took me so long to name.</p><p>There’s something about how the eye parses the world that we rarely talk about in design. We do it with music all the time. A rest between two notes isn’t silence. It’s tension, or release, or the space where meaning lands. Shorten the rest and the phrase rushes. Lengthen it and the notes become separate thoughts. The gap is doing as much work as the sound.</p><p>Spacing on a screen works the same way. Gestalt psychology calls it the <a href="https://lawsofux.com/law-of-proximity/"><strong>law of proximity</strong></a>. Elements that are close together get perceived as belonging together. We do this automatically, without thinking, before we’ve read a single word on the page. It’s one of the primary signals the brain uses to understand structure.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hJrBV35EvME-8-SH6AEmRw.png" /></figure><p>So when you place two elements with 4px between them, you’re not making a layout decision. You’re making a cognitive one. You’re telling someone’s brain: these are related. When you use 64px, you’re saying: these are not.</p><p>I keep coming back to that. The pixel value is a means. The relationship is the message.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0d3ca078c9c7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[From idea to something you can hold]]></title>
            <link>https://medium.com/design-bootcamp/from-idea-to-something-you-can-hold-a188293f7ce9?source=rss-9d7ee8daf241------2</link>
            <guid isPermaLink="false">https://medium.com/p/a188293f7ce9</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[color-theory]]></category>
            <category><![CDATA[design-thinking]]></category>
            <category><![CDATA[mathematical-design]]></category>
            <category><![CDATA[design-systems]]></category>
            <dc:creator><![CDATA[Hal]]></dc:creator>
            <pubDate>Mon, 06 Apr 2026 14:07:38 GMT</pubDate>
            <atom:updated>2026-04-08T22:14:03.842Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*u1DKHXMgrLiL40hjfss5LQ.jpeg" /></figure><p>I’ve always been drawn to the moment an idea stops being abstract and becomes something physical. A sketch on paper. A prototype you can click through. A tool someone else can open and use. There’s a shift that happens in that transition, something changes in how you understand your own thinking when it exists outside your head.</p><h3>The idea</h3><p>I’ve been building a mathematical design library in Figma where every value is proportionally connected to the next. Spacing, typography, layout. All of it derived from a value (e.g. 1.618 or φ), the same proportional logic found in nature, architecture, and music. If we trust these proportions for the Parthenon and for musical harmony, why not for the systems that power our digital interfaces?</p><p>But I kept hitting a wall with colour. Most design systems treat colour scales as a separate concern. You pick a brand colour, then generate tints and shades using percentage-based formulas. Lighter by 10%, darker by 20%. The numbers are arbitrary. They work visually, but they’re disconnected from the proportional logic governing everything else.</p><p>I wanted to know what happens when you apply φ to colour directly.</p><h3>Thinking out loud</h3><p>I started working through the idea in a conversation with Claude. HSB (Hue, Saturation, Brightness) felt like the right colour model because it maps most naturally to how we perceive colour. Hue is the colour itself. Saturation is its intensity. Brightness is how much light it carries.</p><p>The question was simple: what if saturation stepped down by φ from a base colour? Take #FF0000, pure red, at full saturation. Divide by 1.618 at each step. You get 100 → 61.8 → 38.2 → 23.6 → 14.6 → 9.0 → 5.6 → 3.4 → 2.1.</p><p>At some point during the conversation, I realised the idea was already fully formed in our exchange. The logic, the maths, the expected output. It just didn’t exist as anything I could point to yet.</p><h3>Making it real</h3><p>So I asked Claude to turn our conversation into an HTML page where I could plug in any mathematical formula across the three HSB channels. That single request gave me a working tool. Not a mockup or a wireframe, but a functional colour scale generator.</p><p>I brought it into Cursor and used Sonnet and Composer agents to finish the job. Light/dark mode. Better typography. Cleaner file separation. The kind of detail work that turns a rough prototype into something you’d actually want to share.</p><p>The whole thing is now a GitHub page. Pick a base colour, write a formula for each channel, and generate a scale. There are presets to get you started, three different views, and export options for hex, CSS variables, Figma tokens, and JSON.</p><p><strong>Try it here:</strong> <a href="https://hferello.github.io/colour-scale/">hferello.github.io/colour-scale</a></p><h3>The distance between thinking and making</h3><p>What stays with me about this experience is not the tool itself. It’s how short the path was from having the idea to holding the finished thing.</p><p>I’ve had versions of this concept in my head for a while. Mathematical colour scales, φ applied to every channel of HSB. But it lived as a thought, something I could describe to people but couldn’t show them. In one sitting, through conversation alone, it became something physical. Something with a URL. Something someone else can open, use, and build on.</p><p>I think this is what changes when the cost of making things drops close to zero. The ideas that used to sit in notebooks and voice memos and half-finished Figma files start becoming real. Not because the technology is impressive, but because the gap between “I think this could work” and “here, try it” gets small enough that you actually cross it.</p><p>For me, this small tool is one piece of a bigger question I keep coming back to. If mathematical proportion governs the structures we find beautiful in nature, what happens when we let those same proportions govern every layer of a design system? Not just spacing and type, but colour, motion, opacity, everything.</p><p>I don’t have the full answer yet. But now I have a tool to keep exploring, and that feels like progress.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a188293f7ce9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/design-bootcamp/from-idea-to-something-you-can-hold-a188293f7ce9">From idea to something you can hold</a> was originally published in <a href="https://medium.com/design-bootcamp">Bootcamp</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Design thinking is the AI superpower]]></title>
            <link>https://medium.com/design-bootcamp/design-thinking-is-the-ai-superpower-573565c5e932?source=rss-9d7ee8daf241------2</link>
            <guid isPermaLink="false">https://medium.com/p/573565c5e932</guid>
            <category><![CDATA[design-thinking]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[product-design]]></category>
            <category><![CDATA[ux-design]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Hal]]></dc:creator>
            <pubDate>Fri, 03 Apr 2026 19:36:48 GMT</pubDate>
            <atom:updated>2026-04-13T13:58:36.877Z</atom:updated>
            <content:encoded><![CDATA[<h4>The skills that helped me most building a full-stack platform weren’t technical — they were design skills.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mhnxXzX0InD233Gu9mdeqg.png" /></figure><p>I’m a designer who codes a bit. I’ve dabbled in PHP, HTML, and CSS over the years, but always at a beginner level. Nothing that would prepare you for building a full-stack platform from scratch.</p><p>And yet, that’s exactly what I did. I spent 6 months building Play Hopper; a platform that connects families with local playgroup organisers for children’s activities. A real product, with real users, real payments, and real edge cases.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jspBzekmRAdC4wGced4KMg.png" /></figure><p>But here’s the thing that surprised me the most. The skills that carried me through this weren’t the ones I learned along the way. They were the ones I already had.</p><h3>System thinking → Data modelling</h3><p>When I sat down to design the database schema for Play Hopper, I expected it to feel completely foreign.It didn’t. It felt exactly like designing a complex information architecture.</p><figure><img alt="database schema diagram" src="https://cdn-images-1.medium.com/max/1024/1*tHJxMSDVZPZizbLibStwBQ.jpeg" /></figure><p>I needed to model a world where organisers create events, events generate sessions, sessions accept bookings, bookings belong to adults who have children, children have age ranges that determine eligibility, and sessions have capacity limits that differ depending on whether you’re counting adults only or adults plus children. There are waitlists that promote automatically, voluntary “give my spot away” flows, and bookings that can be cancelled, refunded, or converted from waitlist entries. Each with its own financial implications.</p><p>Sound familiar? If you’ve ever designed a complex IA. The kind where you’re mapping out content types, taxonomies, relationships, and states across a large-scale product. You’ve done this before! You’ve just never called it “data modelling.”</p><p>Entities are content types. Relationships are the lines between them. States are the statuses that change how the UI renders. The thinking is identical; you just express it differently. Instead of a sitemap, you write a schema. Instead of a content model in a spreadsheet, you write it in TypeScript with Drizzle ORM.</p><p>But the cognitive work, the part that actually matters, is the same.</p><h3>Edge case obsession → Error handling</h3><p>If there’s one thing designers are trained to do, it’s obsess over states. Not just the “happy path”, but the empty states, the error states, the loading states, the partial states, the “something went wrong but we don’t want the user to panic” states. We sketch them. We prototype them. We argue about them in design reviews.</p><p>It turns out, engineering needs the exact same obsession.</p><p><strong>What happens when two parents try to book the last spot in a session at the same time?</strong></p><p>One succeeds. The other needs to land on a waitlist — seamlessly, without a confusing error message.</p><p>And if the first parent cancels? The waitlisted parent should get promoted automatically, notified via email, and the booking should be flagged as a waitlist conversion for the organiser’s analytics.</p><p>That’s not just code. That’s experience design for a system you can’t see.</p><p><strong>The same thinking popped up everywhere:</strong></p><ol><li><strong>What if a Stripe webhook is delayed?<br></strong> I built a checkout session verification function as a safety net, with a delay mechanism to give webhooks time to process before falling back to manual verification.</li><li><strong>What if a user opens a magic link in a different browser?<br></strong>I refactored the authentication flow to use token first, with a legacy fallback, so the login works regardless.</li><li><strong>What if an organiser needs sessions that don’t follow a recurring pattern?<br></strong>I added a “custom” frequency option, letting them manually manage sessions outside of automatic generation.</li></ol><p>Every single one of these started as the same question designers ask every day: <strong>”But what happens when…?”</strong></p><h3>User flows → System flows</h3><p>Before I wrote a single line of booking logic, I mapped the entire booking process as a user journey. Step by step. Screen by screen. Decision by decision.</p><p>What does the parent see first? How do they select a session? What happens if the session is full? What if the event is free versus paid? What if there’s a late booking fee? What if the child’s age doesn’t match the event’s eligibility criteria? What does the confirmation look like? What email do they receive?</p><p>I mapped all of this out as a flow; the way designers do.</p><figure><img alt="user journey mapping" src="https://cdn-images-1.medium.com/max/1024/1*Lqo3LcAd2zT4h8S6RfEmPQ.jpeg" /></figure><p>And when it came time to implement? The user journey became the engineering spec. Each step in the flow became a function. Each decision point became a conditional. Each screen became a component. The flow I’d already designed told me exactly what to build and in what order.</p><p>This pattern repeated across the entire platform:</p><h4><strong>Organiser onboarding flow</strong></h4><p>From signup to profile creation to event setup to going live, this was a user journey before it was a series of database mutations and action server calls.</p><figure><img alt="onboarding screens for organisers" src="https://cdn-images-1.medium.com/max/1024/1*96g2rXddDAtyP8SaH8q0dw.jpeg" /></figure><h4><strong>The account deletion flow</strong></h4><p>Requiring confirmation, notifying affected users, soft-deleting records, and cleaning up storage. It was designed as a careful off-boarding experience before it became a cascade of database operations.</p><p>The user journey <strong>is</strong> the system architecture. Designers just don’t always realise that’s what they’re producing.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y9M3uJnaFnOXW6rkppK0qw.png" /></figure><h3>What “designing with AI” actually means</h3><p>There’s a conversation happening right now about designers and AI. Most of it focuses on the surface: swap Figma for an AI prototype tool, generate mockups faster, use AI to write copy.</p><p>That’s fine. But it misses the point.</p><p>The real opportunity isn’t about replacing one design tool with another. It’s about going deeper into the system. And when you understand the system well enough, you start making decisions that no AI tool can make for you.</p><h4><strong>Optimise how data loads</strong></h4><p>I implemented lazy-loaded charts with React Suspense, replaced &lt;img&gt; tags with Next.js &lt;Image&gt; for automatic optimisation, and built tab-based session navigation with URL state management so users can bookmark specific views. These aren’t designer decisions or engineer decisions. They’re <strong>experience</strong> decisions that require understanding both sides.</p><h4><strong>Choreograph interactions that genuinely delight</strong></h4><p><strong>Waitlists:</strong> When a waitlisted parent gets promoted to a confirmed booking, the UI transition matters. When a booking card shifts to “cancelled,” the grayscale styling communicates status before the user reads a single word. These are design decisions made at the system level.</p><h4><strong>Make architectural decisions with intention</strong></h4><p>C<strong>apacity count mode</strong>: a real architectural decision where a UX insight (<em>“some organisers count capacity by adults only, others count adults and children together”</em>) became a single schema field that cascades through the entire platform: booking validation, waitlist logic, search results, map pins, event forms, and analytics.</p><p>Observation → architectural choice → system adapts.</p><p><strong>This is what it actually means to design with AI as your collaborator.</strong></p><p>Not delegating the thinking, but elevating it. You use AI to handle implementation velocity while you focus on the decisions that shape the experience: the data model, the edge cases, the flows, the architecture.</p><h3>The evidence is in the details</h3><p>If you want to know whether design thinking translates to engineering quality, look at the details:</p><h4><strong>Inclusivity</strong></h4><p>Full ARIA support, semantic &lt;fieldset&gt; and &lt;legend&gt; forms, keyboard-navigable autocomplete. This wasn’t an afterthought. Accessibility is a design discipline, so it was designed in from the start.</p><h4>Invisible design</h4><p>Google Calendar integration needed automatic create, update, and delete across sessions. Manual sync for missing events. Connection status management. Race condition fixes. It’s a complex system integration, but the design question was simple:</p><p><strong>How should an organiser’s calendar stay in sync with their sessions without them thinking about it?</strong></p><h4><strong>Building trust</strong></h4><p>With environment-aware rules, bot detection on signup and login forms, token-based authentication with cross-browser fallback. Security as a design constraint, not an engineering bolt-on.</p><p>Hundreds of edge cases handled. A platform that went from zero to production with one person. A designer. Making every decision.</p><h3>Designers have always been systems thinkers</h3><p>The gap between design and engineering isn’t as wide as our industry pretends. The cognitive skills are remarkably similar.</p><p><strong>The difference is syntax, not thinking.</strong></p><p>System thinking, edge case obsession, user flow mapping; these aren’t skills that become irrelevant once you open a code editor. They’re the <strong>hardest</strong> skills in the entire process. Knowing <strong>what</strong> to build, <strong>why</strong> to build it, and <strong>what happens when things go wrong</strong>; that’s the hard part.</p><p>And designers are already trained for it.</p><p>AI is accelerating this convergence. When AI handles more of the syntax; the boilerplate, the configuration, the “how do I do X in framework Y” questions.</p><p>What’s left is the thinking.<br>The architecture. <br>The decisions. <br>The empathy for the person on the other side of the screen.</p><p>Designers have always been systems thinkers. We just have new systems to design.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=573565c5e932" width="1" height="1" alt=""><hr><p><a href="https://medium.com/design-bootcamp/design-thinking-is-the-ai-superpower-573565c5e932">Design thinking is the AI superpower</a> was originally published in <a href="https://medium.com/design-bootcamp">Bootcamp</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Build in Features, Not Plans.]]></title>
            <link>https://medium.com/design-bootcamp/build-in-features-not-plans-3fd9b1af4d0e?source=rss-9d7ee8daf241------2</link>
            <guid isPermaLink="false">https://medium.com/p/3fd9b1af4d0e</guid>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[cursor]]></category>
            <category><![CDATA[product-design]]></category>
            <category><![CDATA[product-development]]></category>
            <dc:creator><![CDATA[Hal]]></dc:creator>
            <pubDate>Mon, 23 Mar 2026 09:05:37 GMT</pubDate>
            <atom:updated>2026-03-28T16:39:21.715Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cd8_bpJNFJKvsIJhs4aK_w.png" /></figure><p>It feel like a magic using coding agents to build something. Getting started with a simple prompt “make me this” can seem like the right way to build, scrappy now, fix later.</p><p>Generally, when you look at how successful teams operate, they structure their work: discover the problem, understand their users, what are the goals, what is out of scope, etc.</p><p>All these decisions help build value for the user.</p><p>Keeping track of a feature can become trickier though: break it into tasks, design this, conversation there, decisions get made on the fly, edge cases surface. The original intent can get lost somewhere between the brief and the pull request.</p><p>It’s no different with coding agents, but they lose context of what they’re supposed to be doing, but much quicker.</p><h3>Agents build first. Think never.</h3><p>AI coding agents make this worse.</p><p>Give an agent a prompt and it starts producing immediately. Components. Logic. Layouts. Full speed, no questions. It doesn’t ask who the feature is for. It doesn’t consider what happens when something breaks. It doesn’t check whether what you asked for is actually what you need.</p><h3>What good teams do differently</h3><p>The best teams I’ve worked with do one thing before anyone writes a line of code. Someone slows everything down and asks the uncomfortable questions.</p><p>Not in a doc that lives in Notion. Not in a ticket nobody reads. Right there, before the work starts:</p><ul><li>What problem does this actually solve?</li><li>Who is it for?</li><li>What does success look like?</li><li>What are we explicitly not building?</li><li>What breaks if we get this wrong?</li></ul><p>That conversation shapes everything that follows. Skip it and you’re building on assumptions.</p><h3>So I built that conversation into the tool</h3><p>I created a small open-source add-on for Cursor called <a href="https://github.com/hferello/ai/tree/main/feature">/feature</a>. Run /feature &quot;checkout-flow&quot; and it doesn&#39;t start building. It starts asking.</p><p>One at a time. You can answer, skip, or push back on any of them</p><p>The point isn’t to fill out a form. It’s to make sure the agent and you actually understand what’s being built before a single line of code is written.</p><p><a href="https://github.com/hferello/ai/tree/main/feature">Download it</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*Uh9_sI-28xuaw-5PczEYkA.gif" /></figure><h3>The thinking lives in the files</h3><p>Once the questions are answered, /feature creates a set of files directly inside your project under features/&lt;task-name&gt;/:</p><ul><li><strong>task_plan.md</strong> — the work broken into phases, with status tracking</li><li><strong>findings.md</strong> — research and discoveries along the way</li><li><strong>progress.md</strong> — a session log so nothing falls through the cracks</li><li><strong>documentation.md</strong> — what was built and how it works</li><li><strong>prd.md</strong> — the full requirements, built from your answers</li></ul><p>These aren’t planning documents that live outside the work. They live inside the project. They travel with the code. They’re as much a part of the feature as the components themselves.</p><h3>It criticises itself</h3><p>After the files are created, the agent switches roles and starts reviewing.</p><p>It re-reads everything with one goal: find the problems before the build does.</p><ul><li>Do the goals, user stories, and requirements actually align?</li><li>Are there edge cases implied by the stories but not listed anywhere?</li><li>Did scope quietly grow beyond the original brief?</li><li>For UI work: missing error states, empty states, accessibility gaps?</li></ul><p>But it goes further than a checklist. It challenges the thinking behind the plan.</p><p><em>“Is this must-have actually three features pretending to be one?”</em></p><p><em>“You’re anchored on one approach — have you considered this simpler alternative?”</em></p><p><em>“What is this assuming about the user that might not be true?”</em></p><p>Clear issues get fixed on the spot. Judgment calls get surfaced with context and a recommendation. It’s the feature review you’d normally do on day three.</p><h3>Why this matters for product teams</h3><p>We think in flows, states, and outcomes. We see the whole picture from the start.</p><p>But hand an idea to an AI, or sometimes even to a team, and the nuance evaporates. The feel gets lost. The <em>why</em> gets lost. What comes back is something that technically works but misses the point entirely.</p><p>/feature doesn&#39;t fix that completely. But it forces the conversation that usually gets skipped. And it keeps a record of that conversation inside the project.</p><p>The plan isn’t separate from the feature. It <em>is</em> the feature.</p><h3>Try it</h3><p>Open source, free, one-line install:</p><pre>git clone --depth 1 https://github.com/hferello/ai.git /tmp/cursor-feature-skill &amp;&amp; bash /tmp/cursor-feature-skill/feature/install.sh &amp;&amp; rm -rf /tmp/cursor-feature-skill</pre><p>Restart Cursor, type /feature &quot;your-task&quot;, and see what happens when an AI agent plans before it builds.</p><p>Check it out on Github: <a href="https://github.com/hferello/ai/tree/main/feature">https://github.com/hferello/ai/tree/main/feature</a></p><h3>Inspiration</h3><p>The workflow and “plan with living docs” idea for this skill take their cue from <a href="https://github.com/OthmanAdi/planning-with-files">planning-with-files</a> (Othman Adi). Thank you 🙏</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3fd9b1af4d0e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/design-bootcamp/build-in-features-not-plans-3fd9b1af4d0e">Build in Features, Not Plans.</a> was originally published in <a href="https://medium.com/design-bootcamp">Bootcamp</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Being on life’s rollercoaster]]></title>
            <link>https://medium.com/@hal.is.writing/being-on-lifes-rollercoaster-824dff777439?source=rss-9d7ee8daf241------2</link>
            <guid isPermaLink="false">https://medium.com/p/824dff777439</guid>
            <category><![CDATA[working-parents]]></category>
            <dc:creator><![CDATA[Hal]]></dc:creator>
            <pubDate>Tue, 26 Nov 2024 16:51:10 GMT</pubDate>
            <atom:updated>2024-11-26T16:51:10.841Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ScIBWCwei2DSVW8lyD_ZvQ.jpeg" /></figure><h3>The queue to the rollercoaster — before Aston</h3><p>When we first found that my wife, Jodie, was pregnant, I felt a sense of calm and imagined the many moments we’ll have together as a family. She sat me down, and it felt like a therapy session at the time “Hal I think I’m pregnant”. It was hard to express my emotions. Finding out painted a variety of different feelings and questions. Will I be able to help? Can we financially have a baby? Will I be a good enough dad? What does it mean for our relationship?</p><p>In my heart, I knew I was ready to be a dad, though. Somewhere in there, I thought, “Yeah, this is the right time”. As the days went by, I was able to process it and become more and more excited. :excited:</p><h3>Organising life before the chaos</h3><p>My prepping mind went into gear, and I read several blog posts about how we can best prepare and understand what to expect. While the baby was still inside and we had time, I decided to organise the next 12 months into a Trello board. My wife loved this as she was able to ask the right questions to doctors and midwives and ensure we’re on the right(ish) track.</p><h3>Flat floor</h3><p>We also used this time to get our place clean and as tidy as possible. Keeping Aston’s stuff nearby when we needed it. We also decided to change him on the floor as it would give us more time to interact with him.</p><h3>The many little things</h3><p>A baby’s skin is more transparent during the first few months, and so it becomes easier to do scans of all the different organs and bones. We saw Aston yawn, stretch, and roll. :loveit: My connection with him grew so much at this point.</p><h3>Unwinding before Baby — the Babymoon</h3><p>We decided to go on a three-week holiday around the Great Ocean Road before Aston came into the world. One, we are digital nomads at heart. We love being in different places and exploring different cultures and spaces. Two, our mobility will be greatly limited with a newborn to a small radius around our local area (more than we realised, as we initially thought we would be fine travelling with a baby). This was a great way for us to get out of the routine of being at home and it gave my wife, Jodie, a chance to exercise along beautiful coastal walks.</p><h3>💺 Getting onto the rollercoaster — birth</h3><p>By far the craziest experience I’ve ever been through. So many things to bring, so many things to think about. Jodie’s early labour was very long, over 30 hours. At the time, we were watching the men’s final for the Australian Open. Jodie slipped out before the last game. Again, she sat me down like a therapy session and said “Hal I think I’m going into labour soon.” As time passed, things got more serious, we drove to the hospital and Jodie’s water broke in the car. It felt like a rom-com scene, well, in my head, I’m not sure Jodie thought it was in any way comical… She decided to have a water birth and I’ll save you from all the details, but it was like the movie “Everywhere everything all at once”, at least for me it did. Luckily, Jodie didn’t have any complications, and they were at home the next day. The 15-min drive home from the hospital was the longest drive of my life! I was probably doing 15kph the whole way there 😅 🐌</p><h3>🎢 Riding the rollercoaster — after Aston</h3><p>My life was forever changed when I first held Aston in my arms. The first week was fantastic; he was asleep for most of it. We thought this would be a breeze! Then came the second week, when he started learning to cry. We realised ohhhhh this is what it’s really like. Sleepless nights, nappy changes, and learning the ropes of caring for a fragile little life can be overwhelming, but these moments were also filled with love and bonding that created a strong foundation for our family.</p><h3>Innate self-development</h3><p>I loved seeing how Aston naturally developed things he needed to do during each milestone, like learning to make eye contact, holding his head up, holding things and smiling at us. For the first six weeks before he smiled felt so much harder. When that first smile came, oh wow, we were over the moon. It’s like your manager giving you great feedback! His self-development reminded me of a book by Carl Sagon called <a href="https://www.goodreads.com/book/show/32276.The_Dragons_of_Eden">the Dragons of Eden</a>, which explains how the human brain works and how it’s structured. I started to embrace the learning curve of parenthood by adapting and constantly growing alongside Aston. It also meant recognising that there’s no perfect parent and that it’s okay to make mistakes. I saw early on that it was important to learn from him and strive to be the best parent I can be.</p><h3>Easing into life</h3><p>We were cautious new parents during the first few weeks. A 10-min walk is all we could manage at the beginning. We slowly started to get out for longer and longer trips over the next couple of months. Each time he had more exciting things to see. We even managed a two-hour drive to stay a night in the Blue Mountains. They became unforgettable moments that filled our hearts.</p><h3>Learning to keep all my plates spinning</h3><p>Being a parent comes with many challenges. Balancing work, family, and personal growth can sometimes seem difficult. Finding ways to maintain a healthy balance is essential by prioritising quality time with Aston, setting boundaries at work, and carving out time for self-care. With this approach, I hope to be better equipped to handle the challenges I might face on this rollercoaster.</p><h3>Copy and paste</h3><p>Children naturally copy their closest humans — usually their parents! This means I play a vital part in shaping his values, beliefs, and attitudes. I’ve always believed in demonstrating qualities like kindness, patience, and resilience, and I have been taught these lessons many times in my life. I hope I can pass these essential life lessons on to Aston. My actions, whether big or small, might have a lasting impact on his life, so I promise to strive to be the best role model I can be.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=824dff777439" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>