<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>allan.ltd Journal</title>
    <link>https://allan.ltd/blog</link>
    <description>Notes on design, engineering and shipping products, from the allan.ltd studio.</description>
    <language>en</language>
    <atom:link href="https://allan.ltd/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Disclosure is a component now, so put it in the system</title>
      <link>https://allan.ltd/blog/disclosure-is-a-component-now</link>
      <guid isPermaLink="true">https://allan.ltd/blog/disclosure-is-a-component-now</guid>
      <pubDate>Sat, 15 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>design</category>
      <category>compliance</category>
      <category>ai</category>
      <description>Once telling users what is machine-made is an obligation rather than a courtesy, it stops being a one-off screen and becomes a primitive. Most design systems do not have one.</description>
      <content:encoded><![CDATA[<p>The transparency rules that came into force this month create a requirement that shows up in a lot of places at once: the user has to be able to tell what was produced by a machine. Handle that per feature and you will end up with five different badges, three tones of voice and one surface everybody forgot.</p>
<p>It is a design system problem. The systems I have looked at recently have a component for everything else that carries meaning consistently, and nothing for this.</p>
<h2>What the primitive has to cover</h2>
<ul><li>Inline marking on a piece of generated content, at the content, not near it.</li><li>A persistent marker on a surface where you are talking to a system rather than a person.</li><li>A confidence or provenance affordance for the cases where the output is uncertain or derived.</li><li>A route to the detail, because the short label will never carry the full explanation.</li></ul>
<p>Four variants of one component, with one set of tokens and one piece of copy guidance. Built once it takes an afternoon. Discovered late it is a retrofit across every product surface you own.</p>
<h2>Design it so it can be lived with</h2>
<p>The temptation is to make it loud, because it is a compliance artefact and loud feels safe. Loud gets ignored fastest. A marker that shouts on every message trains the user to stop seeing it inside a day, and you have satisfied the letter of the thing while defeating its purpose.</p>
<p>Quiet, consistent and always in the same relationship to the content works better. The user learns the pattern once, and after that its absence is informative, which is the actual goal.</p>
<h2>Write the copy once</h2>
<p>The wording is the part that fragments. Generated with AI, AI-assisted, automated summary, created by our model. Four teams will pick four phrasings and the product will read like it was assembled from different companies.</p>
<p>Pick the words, put them in the system next to the component, and make the correct thing the easiest thing to reach for.</p>
<h2>The reason to do it properly</h2>
<p>The regulation is the deadline, not the reason. Being straight about what a machine produced is a trust decision that pays out whether or not anyone is checking, and it is much cheaper to build as a primitive now than to reconcile across a product later.</p>]]></content:encoded>
    </item>
    <item>
      <title>Ten models in two weeks is an architecture warning</title>
      <link>https://allan.ltd/blog/dont-build-on-one-model</link>
      <guid isPermaLink="true">https://allan.ltd/blog/dont-build-on-one-model</guid>
      <pubDate>Fri, 14 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>product</category>
      <category>engineering</category>
      <description>The trackers counted roughly ten new model releases from six providers in the first half of this month. If your product has one model's name written into it in more than one place, that pace is a problem you already have.</description>
      <content:encoded><![CDATA[<p>The release trackers logged <a href="https://llm-stats.com/llm-updates" rel="noopener noreferrer" target="_blank">about ten new models from six providers in the first two weeks of August</a>. Whatever the precise count, the cadence is now weekly and shows no sign of settling. Every one of those releases is someone's argument for switching.</p>
<p>The interesting question is not which one is best this week. It is what switching costs you, because at this pace you will do it repeatedly, and the answer is usually written into your codebase long before anyone asks.</p>
<h2>Where the coupling actually hides</h2>
<p>Nobody hardcodes a model name in a hundred places. The lock-in is subtler and lives in four spots.</p>
<ul><li>Prompts tuned to one model's quirks, where the phrasing is load-bearing and nobody remembers why.</li><li>Output parsing that depends on a particular formatting habit rather than an enforced schema.</li><li>Latency assumptions baked into the interface, so a slower model breaks the animation rather than the feature.</li><li>Cost assumptions baked into the pricing, which is the expensive one to unwind.</li></ul>
<p>Only the first is obvious. The other three are discovered during the swap, which is the worst time.</p>
<h2>The cheap insurance</h2>
<p>Force structured output at the boundary and validate it. If the contract is a schema rather than a formatting convention, a model that phrases things differently is not a rewrite.</p>
<p>Then design the interface for the slow case. If your loading state only works at eight hundred milliseconds, you have made model choice a design constraint, and you will find that out under deadline.</p>
<h2>Do not chase the benchmark</h2>
<p>Open models now match proprietary ones on plenty of benchmarks, and benchmark position turns over faster than any team can re-architect. Chasing it is a treadmill with no exit.</p>
<p>The stable position is to be indifferent. Pick on cost, latency and behaviour for your actual task, keep the swap cheap, and re-run your own evaluation when something changes. Your evaluation on your data is the only benchmark that has ever predicted anything about your product.</p>
<blockquote><p>A model is a dependency. Treat it like one, and the release schedule stops being news.</p></blockquote>]]></content:encoded>
    </item>
    <item>
      <title>Being citable is a different job from being crawlable</title>
      <link>https://allan.ltd/blog/being-citable-not-just-crawlable</link>
      <guid isPermaLink="true">https://allan.ltd/blog/being-citable-not-just-crawlable</guid>
      <pubDate>Thu, 13 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>process</category>
      <category>engineering</category>
      <description>Getting read by an answer engine is access. Getting named as the source is attribution. We spent a day on the second one and most of it was deciding what identity we wanted to have.</description>
      <content:encoded><![CDATA[<p>Once the content was readable we had the access problem solved and the attribution problem untouched. A system can quote you perfectly and credit nobody, and from your side those two outcomes look identical in the logs.</p>
<p>What we found is that most of being citable is being unambiguous about who you are, consistently, in a form that does not require inference.</p>
<h2>One identity, referenced everywhere</h2>
<p>We had a person described on the home page and an author name repeated as a string on twenty-five articles. To a machine those are twenty-six unrelated things that happen to share a spelling.</p>
<p>Now there is one identifier for the person and one for the studio, and every article's author field points at the identifier instead of restating the name. The About section, the article bylines and the organisation record all resolve to the same entity. That is not a ranking trick. It is the difference between twenty-six weak claims and one strong one.</p>
<h2>Say the same thing in the format each reader wants</h2>
<ul><li>Structured data for the systems that parse it.</li><li>A plain-text summary at a predictable path for the ones that prefer prose.</li><li>A single file with the full body of everything, so grounding does not require crawling twenty-five URLs and stripping markup.</li><li>A feed that carries complete articles rather than teasers.</li></ul>
<p>The last one is a small thing that matters more than it should. A feed with excerpts only forces a second fetch per item and gives a summariser a truncated version to work from. Full content in the feed is one line of build code.</p>
<h2>Write down how you want to be cited</h2>
<p>We added an explicit attribution line to the plain-text summary saying what to call us and to link the canonical URL of the page quoted. Whether any given system honours it is not in our control. Costing nothing and being occasionally honoured beats leaving it to be guessed.</p>
<h2>The unglamorous conclusion</h2>
<p>Almost none of this is novel. Stable identifiers, honest metadata, complete feeds and plain writing about what you do are the same practices that made sites legible fifteen years ago. The audience changed. The work did not.</p>
<p>The one genuinely new habit is verifying against the served response rather than the source, because the gap between what you wrote and what is delivered is where all of this quietly fails.</p>]]></content:encoded>
    </item>
    <item>
      <title>Your single-page app is invisible to the systems answering questions about you</title>
      <link>https://allan.ltd/blog/your-spa-is-invisible-to-ai</link>
      <guid isPermaLink="true">https://allan.ltd/blog/your-spa-is-invisible-to-ai</guid>
      <pubDate>Wed, 12 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>engineering</category>
      <category>ai</category>
      <category>process</category>
      <description>We measured what a crawler without JavaScript could read from this site. Every article came back as zero words. Google was fine. Everything else was reading a blank page.</description>
      <content:encoded><![CDATA[<p>This site was a client-rendered React application with one HTML file and an empty mount point. Search was fine, because Google renders JavaScript. Then I fetched an article the way a crawler that does not run scripts fetches it, stripped the tags and counted the words. Zero.</p>
<p>Twenty-five articles, all of them substantial, all of them returning an empty document to anything that reads HTML without executing it. That includes most of the systems now grounding answers and recommendations.</p>
<h2>The metadata was never the problem</h2>
<p>We already prerendered per-post titles, descriptions and social images, because share cards break loudly and somebody complains. Body content breaks silently. Nobody reports that an assistant failed to cite you.</p>
<p>So the site looked well optimised by every check we were running. The checks were reading the head.</p>
<h2>The fix was smaller than expected</h2>
<p>The build already generated one HTML file per post to carry the metadata. Rendering the article body into the mount point in that same step was an afternoon. React replaces the container's children when it mounts, so the static version is a pre-render rather than a duplicate. What a crawler reads is what a person sees.</p>
<ul><li>Home page: 0 words before, 146 after.</li><li>Article pages: 0 words before, 480 to 500 after.</li><li>Journal index: 0 words before, the full list of posts and excerpts after.</li></ul>
<p>No framework change, no server-side rendering runtime, no new dependency. The content already existed as structured data at build time, which is the part that made it cheap.</p>
<h2>How to check yours in one minute</h2>
<p>Fetch your most important page with a plain HTTP client, no browser. Strip the tags. Count the words. If the number is near zero, every system that does not run a rendering engine sees nothing, and you will never get a complaint about it.</p>
<p>The disclosure obligations and the structured data and the plain-text summaries all assume there is text on the page to describe. It is worth confirming that assumption before optimising anything built on top of it.</p>]]></content:encoded>
    </item>
    <item>
      <title>AI fluency became a hiring filter, and portfolios have not caught up</title>
      <link>https://allan.ltd/blog/ai-fluency-is-now-a-hiring-filter</link>
      <guid isPermaLink="true">https://allan.ltd/blog/ai-fluency-is-now-a-hiring-filter</guid>
      <pubDate>Tue, 11 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>careers</category>
      <category>design</category>
      <category>ai</category>
      <description>73 percent of design hiring managers now want proficiency with AI tools and 79 percent want experience designing AI products. Those are two different skills and most portfolios show neither.</description>
      <content:encoded><![CDATA[<p>Figma's hiring research puts it plainly: <a href="https://www.figma.com/blog/why-demand-for-designers-is-on-the-rise/" rel="noopener noreferrer" target="_blank">73 percent of hiring managers see a growing need for candidates proficient in AI tools, and 79 percent say the same about designing AI products</a>. I keep seeing those two numbers quoted as one thing. They are not.</p>
<p>Using AI in your process and designing a product that contains a model are unrelated skills. One is about your speed. The other is about handling uncertainty in an interface. A portfolio that demonstrates the first tells a hiring manager nothing about the second.</p>
<h2>Nobody wants to see your prompts</h2>
<p>The most common attempt at showing AI fluency is a case study about the tooling. Generated fifty concepts. Cut research synthesis from days to hours. It reads as a tools review, and the reviewer's next question is whether the output was any good, which the case study never answers.</p>
<p>Speed is table stakes now and it is invisible in the artefact. What is visible is judgement: which of the fifty you kept, and the reason, which is the part that is actually yours.</p>
<h2>What the second number is really asking for</h2>
<p>Designing an AI product means having answered questions that do not come up anywhere else.</p>
<ul><li>What the interface does when the model is wrong, and how the user finds out.</li><li>How the thing expresses uncertainty without becoming useless.</li><li>What the first run looks like before there is any data about this user.</li><li>Where the human decides, and how that boundary is made visible.</li><li>What it costs per interaction, and how the design responds to that cost.</li></ul>
<p>A single screen showing your error and low-confidence states is worth more than a whole case study about workflow acceleration. It is also rarer, which is the point.</p>
<h2>The honest version</h2>
<p>If you have not shipped an AI feature, do not manufacture one. Take a product you know well, find the place a model would plausibly sit, and design the states around the failure. Say clearly that it is speculative. Showing that you understand where it breaks is the signal, and pretending it shipped is a signal too, the wrong one.</p>
<p>The demand is genuinely there. The filter is not asking whether you can operate the tools. It is asking whether you have thought about what happens when the thing in the middle of your product is confidently wrong in front of a customer.</p>]]></content:encoded>
    </item>
    <item>
      <title>Designing for the agent that acts, not the one that answers</title>
      <link>https://allan.ltd/blog/designing-for-the-agent-that-acts</link>
      <guid isPermaLink="true">https://allan.ltd/blog/designing-for-the-agent-that-acts</guid>
      <pubDate>Mon, 10 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ux</category>
      <category>ai</category>
      <category>product</category>
      <description>Gartner expects 40 percent of enterprise apps to carry task-specific agents by the end of this year, up from under 5 percent last year. Chat patterns do not cover any of the hard parts.</description>
      <content:encoded><![CDATA[<p>The projection going around is that <a href="https://www.intodesignsystems.com/agentic-design-systems" rel="noopener noreferrer" target="_blank">40 percent of enterprise applications will embed task-specific agents by the end of 2026</a>, against under 5 percent in 2025. Treat the exact figure with the usual caution. The direction is not really in doubt, and the design consequence is being underestimated.</p>
<p>An agent that answers is a conversation. An agent that acts is a delegation, and delegation has an interface literature that chat borrowed none of.</p>
<h2>The four questions chat does not answer</h2>
<ul><li>What is it doing right now, at a glance, without reading a transcript.</li><li>How do I stop it, and what state am I left in if I do.</li><li>What did it change, expressed as a diff rather than a narrative.</li><li>What happens when it half finished, which is the normal case, not the edge case.</li></ul>
<p>A streaming text box addresses none of these. It shows you prose about work while the work is happening somewhere you cannot see.</p>
<h2>Progress is not the same as status</h2>
<p>A spinner says something is happening. Status says which step, of how many, on which object, reversibly or not. The difference matters most exactly when the user is nervous, which is exactly when they are watching.</p>
<p>The pattern that has worked for us is a plan the user can see before it runs, and the same plan annotated as it executes. It borrows from install wizards and deployment pipelines, both of which solved this problem long before anyone said agent.</p>
<h2>Undo beats confirm</h2>
<p>Confirmation dialogs before every action destroy the reason to delegate. If I have to approve nine steps I have not saved anything, and by step four I am clicking without reading, which is worse than not asking.</p>
<p>Ask once, at the boundary that actually matters, usually the irreversible one. Then make everything inside that boundary undoable and show the user what changed. Cheap reversal is worth more than expensive permission.</p>
<h2>Error recovery is the whole product</h2>
<p>The demo shows the happy path. The product is the other one. An agent that fails halfway through a six-step task has left the user in a state they did not create and cannot see, and the interface owes them an accounting of it.</p>
<p>We now design the partial-failure screen before the success screen. It is a bleak way to start and it produces a better product, because the success screen is easy and everybody already knows what it looks like.</p>]]></content:encoded>
    </item>
    <item>
      <title>Components an agent can reason about</title>
      <link>https://allan.ltd/blog/components-an-agent-can-reason-about</link>
      <guid isPermaLink="true">https://allan.ltd/blog/components-an-agent-can-reason-about</guid>
      <pubDate>Sun, 09 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>design</category>
      <category>ai</category>
      <category>engineering</category>
      <description>Spotify rebuilt their component architecture into independent layers so an AI has less to hold in its head at once. It is the most practical design system idea I have heard this year.</description>
      <content:encoded><![CDATA[<p>The talks from this year's AI design systems track have been circulating, and the one that stuck with me is Spotify's. Their Encore team <a href="https://www.intodesignsystems.com/agentic-design-systems" rel="noopener noreferrer" target="_blank">separated foundations, styles and behaviours into independent layers</a>, and the reason given was not purity. It was that smaller, separable layers create smaller context bubbles for a model to reason about.</p>
<p>That reframing is useful. We have argued about component architecture for a decade using words like coupling and reuse. Here is a new and completely concrete constraint: how much of this does something have to read before it can correctly produce one button.</p>
<h2>Monolithic components are context hogs</h2>
<p>A component that fuses layout, visual style, state and behaviour into one file is a component you cannot ask a narrow question about. To change the padding, a model loads the animation logic and the accessibility wiring too. It burns context on irrelevance and it has more surface on which to go wrong.</p>
<p>Split those concerns and a question about spacing reads spacing. This is the same argument as separation of concerns, with a measurable cost attached for the first time.</p>
<h2>The evaluation part is the bit people skip</h2>
<p>The other half of what Spotify described is a custom evaluation framework that runs prompts against several models and compares the generated components both visually and in code. That is a test suite for your design system's legibility.</p>
<p>Almost nobody has this. Teams publish an MCP server or a documentation site, assume agents can now use the system, and never check. The check is not complicated: ask three models to build five known components from your documentation, and look at what comes back.</p>
<ul><li>If they all get it wrong the same way, your documentation is wrong.</li><li>If they disagree with each other, your documentation is ambiguous.</li><li>If they invent a prop that does not exist, you have a naming problem.</li></ul>
<h2>This is just good documentation with a harsh reviewer</h2>
<p>Everything that makes a design system readable to an agent makes it readable to a new designer in their first week. Predictable names. One obvious way to do the common thing. Constraints stated rather than implied by the examples.</p>
<p>The difference is that the new designer will ask you in Slack when the documentation fails them, and quietly patch the gap with a guess. The model does not ask. It produces confident output built on the gap, and you find out in review. It is a less forgiving reader, which turns out to be useful.</p>]]></content:encoded>
    </item>
    <item>
      <title>Crawled a lot, referred nothing</title>
      <link>https://allan.ltd/blog/crawled-a-lot-referred-nothing</link>
      <guid isPermaLink="true">https://allan.ltd/blog/crawled-a-lot-referred-nothing</guid>
      <pubDate>Sat, 08 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>product</category>
      <category>business</category>
      <description>Automated requests are now about 57 percent of web traffic, and the agents doing the clicking grew roughly 8,000 percent in a year. The number that should worry you is not the traffic. It is the referrals that did not come back.</description>
      <content:encoded><![CDATA[<p>Bots passed humans a while ago. The current measurements put automated requests at <a href="https://thenextweb.com/news/bots-outnumber-humans-internet-ai-agents-traffic" rel="noopener noreferrer" target="_blank">around 57 percent of all HTTP requests</a>, and traffic from agents that actively click links and fill in forms has grown by something close to 8,000 percent in a year. I wrote about the crossover before. What changed this quarter is the shape of the exchange, not the volume.</p>
<p>DataDome logged 17.7 billion AI agent requests in the second quarter. Meta's crawlers accounted for <a href="https://mediacopilot.ai/meta-ai-agent-traffic-datadome-q2-2026/" rel="noopener noreferrer" target="_blank">9.1 billion of them and sent almost nobody back</a>. That is the part worth sitting with. The old bargain was that a crawler took your content and returned attention. One side of that is quietly being withdrawn.</p>
<h2>Why this is a product problem, not an ops problem</h2>
<p>The instinct is to treat it as infrastructure: rate limits, bot rules, a bigger cache. Those are worth doing and they do not address the actual change, which is that a growing share of your audience never arrives as a person.</p>
<p>If an agent reads your pricing page and reports back to its user, your pricing page is now a data source with an interface stapled to it. The comparison is happening off your property. Nothing you do with a hero animation participates in that decision.</p>
<h2>What we changed</h2>
<ul><li>Facts that used to live only in layout now also exist as structured data. Prices, availability, dates, contact routes.</li><li>Anything decision-relevant is in the served HTML rather than assembled after a JavaScript render.</li><li>Comparison-shaped information is written plainly instead of implied by design.</li></ul>
<p>None of that is a concession. Writing down what is true in a form a machine can lift is the same discipline as writing a good spec, and it makes the human page better as a side effect, because vagueness has nowhere to hide.</p>
<h2>The measurement problem</h2>
<p>Your analytics were built for sessions. An agent that reads six pages in one second and produces one answer for one person shows up as inflated traffic and zero engagement, and both numbers are lies about what happened.</p>
<p>We stopped reading traffic as a proxy for interest. Inbound enquiries that mention something specific from the writing tell us more than any pageview chart currently can. It is a cruder instrument. It is measuring the right thing.</p>]]></content:encoded>
    </item>
    <item>
      <title>I found out my own site was blocking AI crawlers, and I never chose it</title>
      <link>https://allan.ltd/blog/who-decided-your-site-blocks-ai</link>
      <guid isPermaLink="true">https://allan.ltd/blog/who-decided-your-site-blocks-ai</guid>
      <pubDate>Fri, 07 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>engineering</category>
      <category>business</category>
      <description>We spent a day making this site legible to answer engines. Then I read the robots.txt actually being served and found half the work was already cancelled by a setting nobody on our side had touched.</description>
      <content:encoded><![CDATA[<p>We had just finished a pass on structured data and a plain-text summary for language models. Everything checked out locally. Then I fetched the robots.txt that production actually serves, rather than the one in our repository, and found a managed block sitting above ours that disallowed ClaudeBot, GPTBot, CCBot, Google-Extended, Applebot-Extended and several others outright.</p>
<p>Nobody on our side wrote that. It was injected at the edge by our CDN, from a default. The file in version control and the file on the wire were two different documents, and only one of them was being obeyed.</p>
<h2>Check the served file, not the source file</h2>
<p>This is the whole lesson and it generalises past robots.txt. Anything a CDN can rewrite, a CDN can rewrite without telling you: security headers, cache directives, redirects, bot policy. If your verification reads the repository, you are testing your intentions rather than your deployment.</p>
<ul><li>Fetch robots.txt from the public URL and read all of it, including anything above your own rules.</li><li>Do the same for your security headers and your canonical tags.</li><li>Do it after every platform change, not only after your own deploys.</li></ul>
<h2>Then make it a decision</h2>
<p>Discovering the block is not the same as knowing what to do about it. There is a real choice here and it is not obvious in either direction. Cloudflare now <a href="https://blog.cloudflare.com/content-independence-day-ai-options/" rel="noopener noreferrer" target="_blank">splits AI traffic into search, agent and training</a> so you can answer them separately, and new defaults that block training and agent traffic on ad-bearing pages arrive in September.</p>
<p>For a publisher whose revenue is impressions, blocking the crawlers that take the content and return no visitors is defensible. For a studio whose writing is how people find it, being absent from the systems people now ask for recommendations is a strange thing to opt into by accident.</p>
<h2>What we settled on</h2>
<p>We allow the crawlers that ground answers and cite sources. We are less relaxed about bulk training collection. That is a position, and positions should be arrived at deliberately, not inherited from whatever your infrastructure vendor shipped as a default this quarter.</p>
<p>The uncomfortable part is that we only found it because we were looking. There is no error, no warning and no dashboard entry when your content quietly stops being readable by the systems that increasingly answer questions on your behalf. Go and read your own robots.txt over HTTP. It takes ten seconds and it is not always the file you think it is.</p>]]></content:encoded>
    </item>
    <item>
      <title>The AI Act stopped being a legal problem and became a UI requirement</title>
      <link>https://allan.ltd/blog/the-ai-act-is-a-ui-requirement</link>
      <guid isPermaLink="true">https://allan.ltd/blog/the-ai-act-is-a-ui-requirement</guid>
      <pubDate>Thu, 06 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>compliance</category>
      <category>product</category>
      <category>ai</category>
      <description>Article 50 of the EU AI Act became enforceable on 2 August. The obligations it creates are not paperwork. They are screens somebody has to design, and most teams have not drawn them yet.</description>
      <content:encoded><![CDATA[<p>The transparency obligations in Article 50 of the EU AI Act <a href="https://digital-strategy.ec.europa.eu/en/news/commission-starts-enforcing-ai-act-rules-and-new-transparency-requirements-2-august" rel="noopener noreferrer" target="_blank">became generally applicable and enforceable on 2 August 2026</a>. I have watched a lot of teams file this under legal review. It is not a legal review problem. Every one of these duties resolves to something a user has to see, which means it resolves to something a designer has to draw.</p>
<p>The scope is wider than most people assume. It applies whether or not your system is classified as high risk, and it applies to systems already on the market, not just new ones.</p>
<h2>Four things you now have to show</h2>
<ul><li>That the person is interacting with an AI system, when that is not already obvious.</li><li>That content was generated or manipulated by AI, in a machine-readable way.</li><li>That emotion recognition or biometric categorisation is being applied to them.</li><li>That a deep fake, or AI-generated text published on a matter of public interest, is what it is.</li></ul>
<p>Read that list as a design brief and it is four disclosure patterns, each with its own placement, timing and persistence question. None of them are hard. All of them are easy to get wrong in a way that either buries the disclosure or wrecks the flow.</p>
<h2>The failure mode is the modal</h2>
<p>The first instinct is always a dialog on first load. It is the worst option available. It interrupts before the user has context for what is being disclosed, it gets dismissed reflexively, and it discloses once for a session in which the AI might appear in six different places.</p>
<p>Disclosure works better attached to the thing it describes. A label on the generated image. A persistent marker on the assistant surface. A line in the message composer rather than a banner above the page. The user reads it at the moment it means something.</p>
<h2>Machine-readable is the part that gets skipped</h2>
<p>The obligation on generated content is not only that a human can tell. It has to be marked in a machine-readable format. That is a pipeline change, not a design change, and it lands on whoever owns the asset export. If your generated images leave the system without provenance metadata, the visible badge in the interface does not cover you.</p>
<h2>What it costs to get ready</h2>
<p>For the products we looked at, this was a week of work, not a quarter. An inventory of every surface where a model touches the user, a decision per surface about what has to be disclosed, and a component to do it consistently. The expensive version is the one where four teams each invent their own badge.</p>
<p>The penalties are up to 15 million euro or 3 percent of worldwide annual turnover, so the case for doing it properly writes itself. But the reason to do it well is that a product which is straight about what is a machine is easier to trust, and that was true before there was a regulation attached to it.</p>]]></content:encoded>
    </item>
    <item>
      <title>Testing a feature that answers differently every time</title>
      <link>https://allan.ltd/blog/testing-ai-features</link>
      <guid isPermaLink="true">https://allan.ltd/blog/testing-ai-features</guid>
      <pubDate>Wed, 05 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>process</category>
      <category>engineering</category>
      <description>Traditional QA asks whether the output matches the expected value. With a model behind the feature there is no expected value, and most teams respond by not testing it at all.</description>
      <content:encoded><![CDATA[<p>Every test suite ever written assumes the same input produces the same output. Feed a model the same prompt twice and you get two different sentences, both arguably correct. The assertion has nothing to attach to.</p>
<p>What I see teams do in practice is skip it. The AI feature is the one part of the product with no automated coverage, which is also the part most likely to embarrass you in front of a customer.</p>
<h2>Test the properties, not the string</h2>
<p>You cannot assert the answer. You can assert things that must be true of any acceptable answer, and those are usually easy to write.</p>
<ul><li>It cites at least one source, and every cited document exists.</li><li>It never claims a number that does not appear in the retrieved context.</li><li>It refuses when the context is empty rather than answering from memory.</li><li>It stays under the length the interface can display without truncation.</li><li>It never returns the user's own input verbatim as the answer.</li></ul>
<p>None of those care what the answer says. All of them catch real failures, and they run in CI like any other test.</p>
<h2>Build the ugly set</h2>
<p>The examples in your demo are not a test set. The useful set is the one built from cases that already went wrong: the support ticket where it hallucinated a refund policy, the account with no data, the customer whose name broke the prompt template.</p>
<p>Thirty of those, run on every change, will tell you more than a thousand synthetic prompts. And unlike a benchmark score, each failure points at something you can actually fix.</p>
<h2>Watch the rate, not the run</h2>
<p>A non-deterministic feature does not pass or fail. It passes at some rate, and the number worth tracking is whether that rate moved after a change.</p>
<p>Run each case a handful of times, record the pass rate, and compare against the previous build. A drop from 96% to 78% on the same set is a real signal even though no individual run is definitive. This is also the only way to catch the quiet regression when a model provider updates something underneath you.</p>
<h2>Where to start</h2>
<ul><li>Write down five properties every acceptable answer must have. Not what it should say, what must be true of it.</li><li>Collect ten real failures from support, sales calls or your own use. That is your first test set and it costs an afternoon.</li><li>Run the set on every deploy and record a pass rate. One number, tracked over time.</li><li>Add each new production failure to the set as it happens. The set is the asset, not the harness.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>AI features have a unit cost, and design decides it</title>
      <link>https://allan.ltd/blog/ai-features-have-a-unit-cost</link>
      <guid isPermaLink="true">https://allan.ltd/blog/ai-features-have-a-unit-cost</guid>
      <pubDate>Sat, 01 Aug 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>product</category>
      <category>design</category>
      <description>Every other interface decision you make is free to run. This one is not. A single default setting can multiply what a feature costs to operate, and the person choosing it is usually not looking at the bill.</description>
      <content:encoded><![CDATA[<p>For twenty years, design decisions were free to operate. Moving a button, adding a step, changing a default: all of it cost time to build and nothing to run. Serving the millionth user cost about the same as the thousandth.</p>
<p>A feature backed by a model breaks that. Every interaction has a marginal cost, and a surprising amount of it is set by interface decisions rather than engineering ones.</p>
<h2>Decisions that move the number</h2>
<ul><li>Autorun versus a button. A summary that generates when the page opens costs on every view. The same summary behind a button costs on the fraction of views where someone wants it.</li><li>How much context you send. Attaching the whole document because it was simpler than deciding what matters is a design choice with a line item.</li><li>Regeneration affordances. A prominent &quot;try again&quot; invites three attempts where one would have done.</li><li>Streaming a response the user abandons. You pay for the whole generation regardless of whether they read past the first line.</li></ul>
<p>None of those look like cost decisions in a design review. All of them are.</p>
<h2>The autorun trap</h2>
<p>Automatic generation almost always tests better. It feels effortless and it demos beautifully, so it wins the room.</p>
<p>Then it ships and the ratio bites. If a fifth of visitors actually wanted the output, four fifths of your spend produced something nobody read, and that ratio holds forever. The version behind a button feels marginally worse in a usability test and costs a fraction to run at scale.</p>
<p>This is a real trade, not an obvious win either way. The point is to make it deliberately instead of discovering it in a finance review.</p>
<h2>Where it changes your pricing</h2>
<p>Flat-rate subscriptions assume usage does not carry marginal cost. Once it does, your heaviest users can become your least profitable, and the pricing page becomes a product decision rather than a marketing one.</p>
<p>That is not an argument for metering everything, which users hate and which makes them ration a feature you want them using. It is an argument for knowing the number before you set the price.</p>
<h2>Where to start</h2>
<ul><li>Work out the cost of one interaction with your main AI feature. One number. Most teams cannot produce it on request.</li><li>Multiply it by monthly active usage and put that figure next to the feature in your roadmap.</li><li>Find anything that generates automatically and measure what fraction of users engaged with the output. Below half, try the button.</li><li>Ask what changes at ten times current volume. If the answer is nothing, you have not done the arithmetic.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Why AI products lose people in week two</title>
      <link>https://allan.ltd/blog/week-two-problem</link>
      <guid isPermaLink="true">https://allan.ltd/blog/week-two-problem</guid>
      <pubDate>Thu, 30 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ux</category>
      <category>product</category>
      <category>ai</category>
      <description>Signups look excellent, week-one usage looks excellent, and then it falls off a cliff. The pattern is consistent enough across products to suggest the cause is structural rather than a marketing problem.</description>
      <content:encoded><![CDATA[<p>The retention curve for AI products has a characteristic shape. Strong signup, strong first session, a decent second, and then a drop far steeper than comparable software.</p>
<p>The usual explanation is that people were just curious. That is part of it, and it is not the whole story, because the same people often come back weeks later and try again.</p>
<h2>The first session is not representative</h2>
<p>Someone trying a product for the first time brings an easy problem. They test it on something they already know the answer to, because that is how you evaluate a tool you do not trust yet.</p>
<p>It works, because easy problems are what models are best at. So the first session sets an expectation calibrated on the easiest input the user will ever provide.</p>
<p>Week two is when they bring real work. Messier input, more context, higher stakes, and now the failure rate they experience is nothing like what they were promised by their own first session. The product did not get worse. The test got harder.</p>
<h2>No path from novelty to habit</h2>
<p>Most AI onboarding teaches you that the thing works. Very little of it teaches you when to reach for it.</p>
<p>Habits form around a trigger, and &quot;whenever you feel like it&quot; is not one. Products that retain tend to have attached themselves to a specific recurring moment: the Monday report, the incoming ticket, the pull request. Products that lose people in week two usually have not named that moment at all.</p>
<h2>The correction that never lands</h2>
<p>The third factor is smaller and more fixable. When a user corrects an output and the same mistake returns tomorrow, they conclude the tool cannot learn, and that conclusion is very hard to reverse.</p>
<p>The fix does not require training on their data. It requires the correction to persist somewhere and be visibly applied, which is mostly an interface problem.</p>
<h2>Where to start</h2>
<ul><li>Compare the inputs from first sessions against week-two sessions. If the second set is meaningfully harder, your onboarding is setting an expectation the product cannot hold.</li><li>Name the recurring moment your product should attach to, and design onboarding to arrive at it rather than at a feature tour.</li><li>Make one correction persist and show the user that it stuck. Measure whether people who correct once come back.</li><li>Put a hard case in onboarding on purpose, with an honest response to it. Trust survives a visible limit better than a hidden one.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>The accessibility deadline that already passed</title>
      <link>https://allan.ltd/blog/the-accessibility-deadline</link>
      <guid isPermaLink="true">https://allan.ltd/blog/the-accessibility-deadline</guid>
      <pubDate>Mon, 27 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>accessibility</category>
      <category>product</category>
      <category>compliance</category>
      <description>The European Accessibility Act became enforceable in June 2025. Most product teams I speak to still treat accessibility as a backlog item, and the penalties in some member states are calculated as a share of turnover.</description>
      <content:encoded><![CDATA[<p>The European Accessibility Act became enforceable on 28 June 2025. It applies to digital products and services sold to consumers in the EU, and it points at EN 301 549, which in practice means WCAG.</p>
<p>The part that tends to get attention is the penalty structure, because it is set per member state and some of it is proportional. Italy calculates up to a share of annual turnover. Spain and the Netherlands run to seven figures. Others are smaller but come with orders that can restrict market access.</p>
<p>I am not a lawyer and this is not advice. But the deadline is behind us, not ahead, and a lot of teams are still planning for it as though it were upcoming.</p>
<h2>Why the usual argument failed</h2>
<p>Accessibility has been argued on ethical grounds for two decades and mostly lost budget fights, because the benefit was diffuse and the cost was immediate.</p>
<p>What changed is not that the ethical argument got better. It is that there is now a number attached to ignoring it, and numbers move roadmaps in a way that principles have not.</p>
<h2>The overlap nobody planned</h2>
<p>Here is the useful part if you are trying to get this funded. Almost everything required for accessibility is also what makes an interface usable by an AI agent.</p>
<ul><li>Semantic structure rather than styled divs, so the thing can be parsed at all.</li><li>Labels that describe purpose rather than appearance.</li><li>State exposed in the markup rather than carried in colour or position.</li><li>Errors that name the constraint and the valid alternative.</li></ul>
<p>Two budgets, one body of work. If the compliance argument is not landing with your leadership, the agent-readiness argument sometimes does, and it buys the same thing.</p>
<h2>What an audit actually finds</h2>
<p>Automated tooling catches roughly a third of real issues, and teams routinely mistake a clean automated report for compliance. The things it misses are the ones that matter: focus order that makes no sense, a modal you cannot escape, a custom component that announces nothing, an error only signalled by a red border.</p>
<h2>Where to start</h2>
<ul><li>Complete your product's main task using only the keyboard. Whatever you cannot finish is your priority list, and it takes twenty minutes to produce.</li><li>Run an automated scan for the cheap wins, then treat the clean report as the beginning rather than the result.</li><li>Check whether you sell to consumers in the EU. If yes, this is a compliance question with a date that has passed, not a quality question.</li><li>Fund it as one piece of work covering both accessibility and agent-readiness. It is the same code either way.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Writing documentation that an agent will read</title>
      <link>https://allan.ltd/blog/documentation-agents-read</link>
      <guid isPermaLink="true">https://allan.ltd/blog/documentation-agents-read</guid>
      <pubDate>Thu, 23 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>engineering</category>
      <category>ai</category>
      <category>process</category>
      <description>Your README was written for a person who can skim, infer and ask a colleague. It is now being consumed by something that does none of those, and the result lands in your codebase at volume.</description>
      <content:encoded><![CDATA[<p>Documentation has always been written for a reader who can fill gaps. They skim to the relevant part, infer the convention from surrounding code, and ask in Slack when something is ambiguous.</p>
<p>An agent does none of that. It reads what is there, treats it as authoritative, and applies it consistently. Which means a vague sentence in your README no longer produces one confused developer. It produces forty files following a rule you did not intend to write.</p>
<h2>Say what not to do</h2>
<p>Most documentation describes the happy path and leaves the boundaries implicit, because a human infers them. The boundaries are the highest-value thing you can write down now.</p>
<p>&quot;Use the shared fetch wrapper&quot; is a preference. &quot;Use the shared fetch wrapper. Never call fetch directly, it bypasses auth refresh&quot; is a rule with a reason, and the reason is what stops it being discarded when it seems inconvenient.</p>
<h2>Examples beat prose</h2>
<p>A paragraph explaining your error handling convention will be interpreted. A short before-and-after pair will be copied.</p>
<pre data-lang="ts"><code>// Wrong: swallows the cause, so the log says nothing useful
try { await save(x) } catch { toast('Save failed') }

// Right: keep the cause, tell the user what to do
try { await save(x) }
catch (e) {
  logger.error('save failed', { id: x.id, cause: e })
  toast('Could not save. Your changes are still here.')
}</code></pre>
<p>Ten lines like that are worth more than a page of description, and they stay accurate longer because they are close enough to real code that someone notices when they drift.</p>
<h2>Delete more than you add</h2>
<p>A stale instruction is worse than no instruction. A person reads &quot;we use Redux&quot; in a codebase with no Redux and ignores it. An agent reads it and installs Redux.</p>
<p>The same applies to volume. Everything in the file competes for attention with everything else, so a long document with three critical rules buried in it performs worse than a short one containing only those three.</p>
<h2>The document is now testable</h2>
<p>This is the part I find genuinely new. You can check whether your documentation works by giving an agent a real task and reading what it produces. Where it goes wrong points at a specific sentence.</p>
<p>That is a feedback loop documentation has never had. Previously the only signal was someone eventually complaining.</p>
<h2>Where to start</h2>
<ul><li>Give an agent a small real task using only your current docs. Read the output as a review of the documentation, not of the model.</li><li>For your five most important conventions, add the prohibition and the reason, not just the preference.</li><li>Replace your longest explanatory paragraph with a wrong-and-right code pair.</li><li>Delete every instruction referring to something no longer in the codebase. Do this before adding anything new.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>What actually happened to design roles in the last two years</title>
      <link>https://allan.ltd/blog/designers-are-being-sorted</link>
      <guid isPermaLink="true">https://allan.ltd/blog/designers-are-being-sorted</guid>
      <pubDate>Wed, 22 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>careers</category>
      <category>design</category>
      <description>Adoption of AI design tools is near universal, but the headcount collapse people predicted did not arrive. Something else happened instead, and it shows up clearly if you look at which briefs are getting paid for.</description>
      <content:encoded><![CDATA[<p>88% of businesses now use AI design tools. Only 18% report that it reduced their need for designers. Those two numbers sit oddly together, and most of the argument online comes from picking one and ignoring the other.</p>
<p>The pattern I see in hiring conversations and in the briefs that come through the studio is not fewer designers. It is a split in what people are being paid to do.</p>
<h2>The work that got cheaper</h2>
<p>One tier of design work was always a rendering job. The brief arrived fully specified and the task was to produce the artefact. Resize this campaign into nine placements. Same layout, different market. Turn this deck outline into slides.</p>
<p>That work priced on time, and the time collapsed. A studio that used to quote three days for a campaign resize now quotes half a day, because that is what it takes. Clients found out at roughly the same speed everyone else did.</p>
<p>Nobody I know enjoyed that work. It was also, for a long time, the entry point into the profession and the way juniors built judgement by volume. That part has no obvious replacement yet, and I do not think the industry has been honest about it.</p>
<h2>The work that got more expensive</h2>
<p>The other tier starts before the brief exists. Someone has to decide what should be built, argue for cutting the feature the stakeholder asked for, and notice that the real problem is in onboarding rather than the dashboard everyone is staring at.</p>
<p>That work got more valuable, not less, and the reason is mechanical. Generation removed the cost of building the wrong thing. When a wrong direction took six weeks to surface, the market self-corrected slowly. When it takes two days, teams can now produce three wrong directions per sprint, and the constraint moves to whoever decides which direction is right.</p>
<h2>How the split shows up in practice</h2>
<ul><li>Briefs that arrive as a problem statement, not a feature list, are up. Briefs that arrive as a list of screens are down.</li><li>Discovery is being paid for separately more often, because clients have learned that the build is no longer the expensive part.</li><li>Rates for execution-only work are under pressure. Rates for the work that ends in a written recommendation are not.</li></ul>
<p>None of this is a prediction. It is what the last eighteen months of proposals in one small studio looked like, and I would be careful generalising too far from that. But the direction matches what the survey numbers imply.</p>
<h2>Where to start</h2>
<ul><li>Look at your last ten pieces of work and mark each one as either &quot;the brief was already decided&quot; or &quot;we helped decide the brief&quot;. The ratio is your exposure.</li><li>In the next project, ask for the meeting before the brief. Even one hour of framing changes what you are being judged on later.</li><li>Write down the recommendation you made and what happened. Not the screens. That record is what the second tier of work is bought on.</li><li>If you manage juniors, replace the volume work they used to learn from with review work. Have them critique generated output against a brief. It builds the same judgement without the busywork.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Your design system isn't ready for AI agents</title>
      <link>https://allan.ltd/blog/your-design-system-isnt-ready-for-ai</link>
      <guid isPermaLink="true">https://allan.ltd/blog/your-design-system-isnt-ready-for-ai</guid>
      <pubDate>Mon, 20 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>design-systems</category>
      <category>ai</category>
      <category>engineering</category>
      <description>A system built for humans encodes what things look like. Agents need to know why. Here are the four gaps that turn up in almost every audit, and what closing them actually involves.</description>
      <content:encoded><![CDATA[<p>Design systems were written for people who can ask a follow-up question. That assumption is load-bearing, and it quietly breaks the moment a coding agent starts consuming the system instead of a designer.</p>
<p>Four things go wrong. They are not exotic. Every system I have audited in the last year has at least three of them.</p>
<h2>1. Three sources of truth that disagree</h2>
<p>The documentation describes what someone intended two years ago. The tokens carry a decision nobody migrated. The shipped components drifted toward whatever went out under deadline pressure.</p>
<p>A designer handles this without noticing. They read the room, glance at what production actually does, ask in Slack, pick the version that looks right. The contradiction never surfaces because a human absorbs it.</p>
<p>An agent has no room to read. It resolves the conflict by picking whichever source it saw most recently, then applies that choice consistently across forty screens before anyone opens a pull request. The failure is not that it guesses. It is that it guesses uniformly and at volume.</p>
<h2>2. Documentation that describes appearance, not intent</h2>
<p>Most component docs say what the component looks like and which props it takes. Very few say when to use it and, more importantly, when not to.</p>
<p>&quot;Use the destructive button variant for actions that cannot be undone&quot; is a rule an agent can apply. &quot;Destructive button: red, 40px height, uppercase label&quot; is not a rule. It is a description, and the agent will happily use it for a cancel action that undoes nothing.</p>
<pre data-lang="md"><code>## Button, destructive

Use when: the action is irreversible and the user
cannot recover the previous state.

Do not use when: the action is reversible, or when
an undo affordance exists. Use the default variant.

Never place two destructive buttons in one view.</code></pre>
<p>That is three lines longer than what most systems have, and it is the difference between a rule and a swatch.</p>
<h2>3. No distinction between what an agent may do alone</h2>
<p>Teams tend to treat agent output as one category, which forces a binary choice between reviewing everything and trusting everything. Neither survives contact with real volume.</p>
<p>The version that works is a graded one. Some changes go straight in, some open a draft pull request for a human, some are only ever suggestions. Token renames and copy edits are not the same risk as a new component variant, and treating them identically is what makes review fatigue set in.</p>
<ul><li>Auto-apply: spacing corrections, token substitutions where a deprecated token has a documented successor.</li><li>Draft for review: new component instances, layout changes, anything touching a shared pattern.</li><li>Suggest only: new variants, new tokens, anything that would extend the system rather than use it.</li></ul>
<h2>4. Components documented as one monolithic thing</h2>
<p>A single page covering every prop, state, variant and edge case is fine for a human who skims to the part they need. Fed to an agent as context, it is mostly noise competing with the twenty percent that matters for the task at hand.</p>
<p>Brad Frost calls the fix progressive disclosure of context. Structure the documentation so the relevant slice can be retrieved on its own rather than shipping the whole page every time.</p>
<h2>Where to start</h2>
<p>Not with a rewrite. Systems teams already spend a large share of their time on maintenance, and a full re-authoring pass tends to stall around the third component.</p>
<ul><li>Pick the five components that appear in the most screens. Reconcile docs, tokens and code for those five only, and make production the tiebreaker.</li><li>Add a &quot;use when / do not use when&quot; pair to each of those five. Two sentences each is enough to start.</li><li>Write down your trust levels before you need them, even informally. Which changes can an agent land without a human, and which cannot.</li><li>Run a real task through an agent against the current docs and read what it produces. The first wrong output usually points straight at the contradiction you have been living with.</li></ul>
<p>The uncomfortable part of all this is that none of it is new work. The ambiguity was always a defect. It was just being paid for quietly, by people, one Slack question at a time.</p>]]></content:encoded>
    </item>
    <item>
      <title>When visual style stops being a moat</title>
      <link>https://allan.ltd/blog/ai-made-imitation-free</link>
      <guid isPermaLink="true">https://allan.ltd/blog/ai-made-imitation-free</guid>
      <pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>design</category>
      <category>ai</category>
      <category>craft</category>
      <description>For a decade a recognisable look was something clients paid a premium for and competitors needed months to copy. That gap closed. What is left to sell is the part that was always harder to put in a deck.</description>
      <content:encoded><![CDATA[<p>A distinctive visual style used to function as a moat. You developed one over years, clients paid for the association, and a competitor who wanted the same effect needed to hire similar people and spend similar time.</p>
<p>That gap is now a few prompts wide. You can hand a model three reference images and get something in the neighbourhood immediately.</p>
<h2>What that actually kills</h2>
<p>It is worth being precise, because the panicked version of this argument overstates it. What became cheap is imitation of a finished look. What did not become cheap is arriving at a look that is right for a specific problem in the first place.</p>
<p>The business model that dies is the one where the studio's aesthetic was the product and every client got a version of it. That was never really design work. It was execution scarcity wearing a portfolio.</p>
<h2>Why models drift toward the middle</h2>
<p>A generative model is trained on the average of what already exists, and it is optimised to produce plausible output. Plausible is the operative word. It reliably lands near the centre of its training distribution, which is exactly where the competent and forgettable version of any design sits.</p>
<p>That is not a temporary limitation to be fixed by a better model. It is what the objective function asks for. The deliberately odd choice, the one that reads as wrong until you understand the constraint behind it, is by definition not the most probable next token.</p>
<h2>What clients are actually buying now</h2>
<p>In practice the thing that survives is the reasoning, which means the deliverable has to change shape. Not just the screens, but the record of why they are like that.</p>
<ul><li>Why this flow has four steps when the competitor does it in one, and what breaks if you compress it.</li><li>Which feature we argued against, what the client wanted it for, and what we proposed instead.</li><li>Why the empty state got more attention than the dashboard, and what the data said about where people actually arrive.</li></ul>
<p>None of that is copyable in four prompts, because none of it is visible in the output. A competitor can clone the interface and still not know which parts were load-bearing.</p>
<h2>Where to start</h2>
<ul><li>Add a decisions section to your next case study. Three decisions, what the alternative was, why you chose. Keep it to a page.</li><li>In the next pitch, lead with the diagnosis rather than the visual direction. If the client cannot tell your diagnosis apart from a competitor's, that is the real problem to solve.</li><li>Audit your own portfolio for pieces where you cannot remember why anything is the way it is. Those are the ones a model can now produce.</li><li>Charge separately for the thinking. If it is bundled into the price of screens, it will keep being valued like screens.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Designing for generative UI: constraints instead of screens</title>
      <link>https://allan.ltd/blog/screens-are-becoming-an-output</link>
      <guid isPermaLink="true">https://allan.ltd/blog/screens-are-becoming-an-output</guid>
      <pubDate>Mon, 13 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>ux</category>
      <category>generative-ui</category>
      <description>When the model composes the layout at runtime, the screen stops being the deliverable. What replaces it is a set of rules about what the interface is allowed to become, including the worst version it can produce.</description>
      <content:encoded><![CDATA[<p>Responsive design forced a shift that took the industry about five years to absorb. Stop drawing one screen, start drawing a system that holds up at any width. Generative UI asks for the same shift one level further out.</p>
<p>If the layout is assembled at runtime from user intent, then handing over a composition is handing over a single sample of the output. Useful as an illustration. Not a specification.</p>
<h2>What the deliverable becomes</h2>
<p>Four categories of rule cover most of it, and they are worth writing down separately because teams tend to only produce the first one.</p>
<ul><li>Composition rules. Which components may appear together, and which combinations are forbidden. A confirmation dialog and an inline edit affordance for the same record should probably never co-exist.</li><li>Priority rules. What wins when three things are all technically relevant. Without this the model surfaces whatever it scored highest, which is not the same as what matters.</li><li>Confidence rules. What the interface does when the model is sure, and what changes when it is not. This is a visual state, not an error path.</li><li>The floor. The worst layout the system is permitted to produce.</li></ul>
<h2>The floor is the part people skip</h2>
<p>Everyone designs the happy path, because that is what gets shown in the review. The floor is the interesting artefact, and it is the one that stops a generative interface embarrassing you in front of a customer at two in the morning.</p>
<p>Concretely, the floor is a set of guarantees that hold no matter what the model decides. There is always a way back. Primary actions never move below the fold. Nothing renders more than two nested levels of generated structure. If confidence drops below a threshold, the layout falls back to a fixed template rather than improvising.</p>
<p>Writing those down is unglamorous and it is the only part of the spec that is genuinely enforceable in code.</p>
<h2>What this does to review</h2>
<p>You cannot approve a generative interface by looking at a screen, because the screen you are looking at is one draw from a distribution. Review has to move to sampling: generate twenty outputs across a spread of realistic inputs, including the ugly ones, and look at the worst three.</p>
<p>That is a different meeting than a design review, and it needs different inputs. Real data, including the account with one record and the account with fifty thousand.</p>
<h2>Where to start</h2>
<ul><li>Take one screen in your product that is a candidate for generation and write its floor. Five guarantees, one sentence each.</li><li>List the component pairs that must never co-occur. This is usually a short list and nobody has ever written it down.</li><li>Define what low confidence looks like visually before you build the feature, not after the first complaint.</li><li>Change one design review into a sampling review. Twenty generated outputs, worst three on screen, decide from those.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Reviewing AI-generated code: what to keep and what to delete</title>
      <link>https://allan.ltd/blog/vibe-coding-isnt-the-flex</link>
      <guid isPermaLink="true">https://allan.ltd/blog/vibe-coding-isnt-the-flex</guid>
      <pubDate>Wed, 08 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>engineering</category>
      <category>craft</category>
      <description>Agents write working code quickly and generously. The generosity is the problem. Most of what comes back is speculative, and the skill that matters now is deciding which parts were load-bearing.</description>
      <content:encoded><![CDATA[<p>Generating a working feature in an afternoon stopped being remarkable. Most teams can do it. The interesting question moved downstream, to what you do with the output.</p>
<p>Agents are good and they are relentlessly generous. Ask for a form and you get validation nobody requested, a configuration layer that will never be configured, and error handling for states that cannot occur given the call sites.</p>
<h2>Why the extra code is not free</h2>
<p>Every speculative abstraction is something the next person has to read before they can change anything. It is another branch that can rot when a dependency moves. It is one more place a bug can sit unnoticed, because nobody exercises the path.</p>
<p>The cost does not show up in the pull request. It shows up nine months later when someone needs to change the thing and has to first work out which of the four code paths is live.</p>
<h2>The four things I delete every time</h2>
<ul><li>Options with one caller. A parameter that is always passed the same value is not flexibility, it is a branch pretending to be a feature.</li><li>Error handling for impossible states. If the type system or the call site rules out null, catching null adds a lie to the code.</li><li>Wrapper layers with no second implementation. An interface with exactly one implementer is indirection, and it will still be there when the second implementer never arrives.</li><li>Comments restating the line below. Generated code narrates itself constantly and it ages worse than the code does.</li></ul>
<h2>The one thing I almost always keep</h2>
<p>Tests. Agents write more of them than most humans will, and coverage of the boring cases is genuinely useful. The caveat is that generated tests tend to assert what the code does rather than what it should do, so they pass by construction and catch nothing.</p>
<p>The cheap check is to break the implementation on purpose and see whether the test fails. If it does not, the test is describing the bug, not preventing it.</p>
<h2>Reviewing it like what it is</h2>
<p>The mental model that works is a fast, confident, slightly overeager junior. Not because the code is bad, but because the failure mode is the same. Reasonable-looking work, produced faster than it can be considered, with an instinct to add rather than remove.</p>
<p>You would not merge that unread from a person. The volume is the only thing that changed.</p>
<h2>Where to start</h2>
<ul><li>On your next generated pull request, delete every parameter with a single call site before reviewing anything else. It usually removes a third of the diff.</li><li>Pick one generated test and break the code it covers. If it still passes, you have learned something about all of them.</li><li>Add a line to your review checklist: what in this diff exists because it was asked for, and what exists because the model likes symmetry.</li><li>Track diff size over a month. If it is growing while feature count is flat, the generosity is winning.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>How to tell whether your AI tools actually made the team faster</title>
      <link>https://allan.ltd/blog/seven-tools-and-no-faster</link>
      <guid isPermaLink="true">https://allan.ltd/blog/seven-tools-and-no-faster</guid>
      <pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>process</category>
      <category>tools</category>
      <description>The average designer's toolstack went from three to seven in a year, and nearly half of teams have not settled. Everyone reports feeling faster. Very few have measured whether the work moves through the studio quicker.</description>
      <content:encoded><![CDATA[<p>Ask designers whether AI tools improved their output and the answer is overwhelmingly yes. Ask how many tools they now use and the average went from three to seven in twelve months, with close to half still describing their setup as unsettled.</p>
<p>Both answers are honest. Together they describe a trap, because per-task speed and end-to-end delivery time are different measurements and only one of them shows up on an invoice.</p>
<h2>Where the time goes back</h2>
<p>Each tool is genuinely faster at its task. What each one also adds is a boundary, and boundaries are where the time reappears.</p>
<ul><li>Another place where work lives, which means another place to look when something is missing.</li><li>An export step, and usually a manual one, because the two tools do not share a format.</li><li>A sync problem when the client changes their mind, since the change now has to land in four places rather than one.</li><li>A subscription and an access list, which is somebody's afternoon every quarter.</li></ul>
<p>None of those are visible in a demo. All of them are visible in the gap between when a client asks for a change and when they see it.</p>
<h2>The measurement that settles it</h2>
<p>Per-task speed is easy to feel and easy to fool yourself about. The number worth tracking is cycle time on a change request: the client asks, and you measure until they can see it. Nothing else in the middle counts.</p>
<p>That figure exposes tool sprawl in a way that individual timings never will, because every boundary crossing lands inside it. If your per-task times all improved and cycle time did not move, the tools are fine and the seams are eating the gain.</p>
<h2>One rule that has been worth more than any tool</h2>
<p>Nothing new gets added unless it replaces something. Not complements. Replaces.</p>
<p>It sounds arbitrary and the effect is that every adoption decision has to name a victim. If nobody can say which existing step dies, the new tool is not a gain, it is a tab. That single constraint has killed more bad purchases for us than any evaluation matrix.</p>
<h2>Where to start</h2>
<ul><li>Measure cycle time on the next five change requests. Ask to see it, then look, and write down both timestamps. Five is enough to see a pattern.</li><li>List every tool the team touched last week and mark which step of the work it owns. Two tools owning one step is where the sync tax lives.</li><li>Apply the replacement rule to the next adoption. If nothing dies, do not add it.</li><li>Re-measure cycle time a month after any change. Feeling faster is not evidence.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Pricing design work when AI made you faster</title>
      <link>https://allan.ltd/blog/clients-are-doing-the-math</link>
      <guid isPermaLink="true">https://allan.ltd/blog/clients-are-doing-the-math</guid>
      <pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>agency</category>
      <category>business</category>
      <category>ai</category>
      <description>Nearly a third of agencies are getting pushback on hourly rates, with clients naming AI as the reason. They have a point, and arguing the point is the losing move. The problem is upstream, in the unit you sell.</description>
      <content:encoded><![CDATA[<p>The conversation now goes the same way most weeks. The client has seen a demo. They have a rough sense of what these tools do. And they are asking, quite reasonably, why the estimate looks the same as it did two years ago.</p>
<p>You can argue. You will lose, because the premise is correct. The work does take less time than it used to.</p>
<h2>The structural problem with billing hours</h2>
<p>If you sell hours, efficiency is something you have to hide from your own client. Every improvement you find reduces your revenue on the same piece of work, so the incentive is to not mention it.</p>
<p>That was always slightly awkward. It became untenable when clients got their own access to the same tools and could estimate the new floor themselves.</p>
<h2>What outcome pricing fixes and what it does not</h2>
<p>Pricing the outcome realigns the incentive immediately. Getting faster becomes profitable rather than self-defeating, and the conversation moves from how many hours to what this is worth. That second conversation is better in every way.</p>
<p>What it does not fix, and what nobody warns you about, is that all of the estimation risk moves onto you. On hourly, a vague scope is the client's problem and they pay for the discovery as it happens. On a fixed outcome, a vague scope comes out of your margin, and you find out in week five.</p>
<h2>The mechanism that makes it survivable</h2>
<p>The fix is not better estimating. We tried that and were wrong at roughly the same rate, just with more confidence.</p>
<p>What worked was splitting discovery into its own paid engagement with its own price, ending in a written scope both sides sign. It is small, it is bounded, and its only deliverable is the definition of the real project.</p>
<p>That moves the guessing to the one place where guessing wrong is cheap. It also gives the client an exit that does not feel like failure, which makes them more willing to start.</p>
<h2>Where to start</h2>
<ul><li>Take one service line, the one you have delivered most often, and price it as an outcome. You already know its true cost from history.</li><li>Write a discovery offer: fixed fee, fixed duration, and a signed scope as the deliverable. Two weeks is usually enough.</li><li>Put a change mechanism in the contract before you need it. Out-of-scope work gets quoted, not absorbed.</li><li>Keep tracking hours internally even after you stop billing them. It is the only way to know whether your outcome prices are right.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Designing interfaces that AI agents can actually use</title>
      <link>https://allan.ltd/blog/half-your-users-arent-human</link>
      <guid isPermaLink="true">https://allan.ltd/blog/half-your-users-arent-human</guid>
      <pubDate>Fri, 26 Jun 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>ux</category>
      <category>agents</category>
      <description>Gartner expects around 40% of enterprise apps to embed task-specific agents by the end of this year. Those agents will use your product without looking at it, and several common design habits stop working entirely.</description>
      <content:encoded><![CDATA[<p>Gartner expects roughly 40% of enterprise applications to have task-specific agents embedded by the end of this year, up from under 5% in 2025. Whatever the exact number turns out to be, the direction is not in dispute.</p>
<p>Those agents are going to use your product. They are never going to look at it. That single fact breaks a set of assumptions most interfaces are built on.</p>
<h2>What stops working</h2>
<ul><li>Meaning carried only in colour or position. A red badge that means overdue is invisible unless the state is also in the markup.</li><li>Flows that depend on remembering the previous screen. Anything held in component state and never reflected in the URL or the DOM cannot be resumed.</li><li>Error messages written as reassurance. &quot;Something went wrong, please try again&quot; gives an agent nothing to act on, so it retries the same failing call.</li><li>Confirmation patterns that rely on hesitation. A human pauses at a destructive dialog. An agent does not have a flinch.</li></ul>
<h2>The error message point is bigger than it looks</h2>
<p>Once an agent is a consumer, your error copy is an API contract. It is the only channel through which the system tells the caller what to do differently.</p>
<p>&quot;That date is not available&quot; is a dead end. &quot;That date is outside the booking window, which opens 90 days ahead&quot; tells the caller what to try instead. The second version is better for people too, which is the pattern with most of this.</p>
<h2>The upside nobody expected</h2>
<p>Almost everything that makes an interface legible to a machine also makes it legible to a screen reader. Semantic structure. Honest labels. State you can address directly rather than infer from pixels. Errors that say what to do.</p>
<p>The accessibility argument for all of this has been on the table for fifteen years and mostly lost budget fights. It is about to get funded for the least romantic reason imaginable, which is that enterprise customers want their agents to work. I will take it.</p>
<h2>Where to start</h2>
<ul><li>Take your most common task and try to complete it from the accessibility tree alone. Whatever you cannot do is what an agent cannot do.</li><li>Audit your ten most frequent error messages. Rewrite each one to name the constraint and the valid alternative.</li><li>Make sure every meaningful state has a text or attribute representation, not just a colour.</li><li>Put the important state in the URL. If a flow cannot be resumed from a link, it cannot be resumed by anything.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Designing for uncertainty in AI features</title>
      <link>https://allan.ltd/blog/if-your-ai-cant-say-im-not-sure</link>
      <guid isPermaLink="true">https://allan.ltd/blog/if-your-ai-cant-say-im-not-sure</guid>
      <pubDate>Wed, 24 Jun 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ai</category>
      <category>ux</category>
      <category>trust</category>
      <description>Most AI features ship with one visual state: confident. The model is wrong some of the time and the interface looks identical either way, which quietly transfers the whole verification burden to the user.</description>
      <content:encoded><![CDATA[<p>A feature that is right 90% of the time and presents everything with the same certainty is worse than one that is right 70% of the time and tells you which is which. That sounds wrong until you think about what the user is actually doing.</p>
<p>Their job was never reading the output. It is deciding whether to trust it. If the interface gives them nothing to decide with, they have to verify everything, and a tool you fully verify has saved you nothing.</p>
<h2>Confidence is a design surface, not a model property</h2>
<p>Teams tend to treat confidence as something the model either exposes or does not, and then stop. But most of what a user needs is not a probability score. It is a set of cues about where the answer came from.</p>
<ul><li>Retrieved versus generated. If part of the answer is quoted from a real document and part was written, those should not look identical.</li><li>Coverage. Was this drawn from twelve sources or one. That difference matters more to a reader than a percentage.</li><li>Recency. An answer built from a document last updated in 2019 deserves a mark.</li><li>Disagreement. If the sources conflict, saying so is more useful than silently picking one.</li></ul>
<h2>Making &quot;I don't know&quot; a real state</h2>
<p>In most products, low confidence falls through to the error path or, worse, to a confident guess. Neither is designed. Both are the absence of a decision.</p>
<p>A designed version looks different: it says what it could not establish, shows what it did find, and offers the next action. &quot;I could not find a stated refund window for this plan. Here are the two policy documents I searched. Ask the account team?&quot; That is a useful answer even though it answers nothing.</p>
<h2>Correction has to stick</h2>
<p>If a user fixes a wrong output and the same error returns next session, they stop correcting and start distrusting. The loop matters more than the accuracy rate, because it is the part the user can feel working.</p>
<p>Showing that a correction persisted is a small piece of interface with a disproportionate effect on whether people keep using the feature.</p>
<h2>Where to start</h2>
<ul><li>Find every AI output in your product and ask what its low-confidence state looks like. If the answer is &quot;the same&quot;, you have a design gap rather than a model gap.</li><li>Add source attribution inline, next to the specific claim, not in a footer. Footers do not get read.</li><li>Write the copy for &quot;I could not determine this&quot; before you build the feature. It is harder than it sounds and it shapes the rest.</li><li>Instrument corrections. If you cannot see how often users override the output, you cannot tell whether trust is improving.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>The case for calm interfaces in AI products</title>
      <link>https://allan.ltd/blog/the-most-impressive-thing-is-boring</link>
      <guid isPermaLink="true">https://allan.ltd/blog/the-most-impressive-thing-is-boring</guid>
      <pubDate>Wed, 17 Jun 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ux</category>
      <category>design</category>
      <category>ai</category>
      <description>Shimmer borders, streamed text, sparkle icons. Most AI products are currently signalling their own cleverness on every interaction. That reads well in a demo and badly on the fortieth use of the day.</description>
      <content:encoded><![CDATA[<p>There is a house style in AI products right now that treats every response as an event. A shimmer on the border while it thinks. Text typing itself out at reading speed even though the whole response arrived at once. A sparkle icon, in case you had forgotten which part is the clever bit.</p>
<p>It works the first time. It signals capability to someone evaluating the product. The problem is that evaluation happens once and use happens daily.</p>
<h2>The artificial streaming case</h2>
<p>Streaming text made sense when it reflected reality. The tokens genuinely arrived over several seconds and showing them early let people start reading sooner.</p>
<p>A lot of implementations now hold a complete response and animate it out anyway, because it looks like thinking. That converts a fast interaction into a slow one on purpose, and users who read faster than the animation are left waiting for a machine to finish performing.</p>
<blockquote><p>Novelty is a loan against attention. It comes due on the fortieth use.</p></blockquote>
<h2>What calm actually means here</h2>
<p>Not undesigned, and not featureless. It means the AI is load-bearing without being loud, and every piece of motion is carrying information rather than signalling effort.</p>
<ul><li>Animate to show where something came from or went. Do not animate to fill time.</li><li>Reserve the strongest visual treatment for the thing that needs the most scrutiny, which is usually the output the user is about to act on.</li><li>Let fast things be fast. If the response is instant, show it instantly.</li><li>Drop the badge. If the feature is good, the user does not need reminding which part was the model.</li></ul>
<h2>Why this is a commercial argument, not a taste one</h2>
<p>Products in this category are moving from novelty adoption to daily use, and the qualities that win those two phases are different. Demo-friendly effects convert evaluators. Restraint retains users, because retention is decided by people who have already seen the trick and now just want the task finished.</p>
<h2>Where to start</h2>
<ul><li>Find every animation in your AI surface and ask what information it carries. Remove the ones where the answer is &quot;it looks considered&quot;.</li><li>If you fake streaming, try shipping the instant version to a portion of users and watch task completion time.</li><li>Use your own product for a full working day. The things that irritate you by mid-afternoon are the ones costing retention.</li><li>Move the visual emphasis to the review step rather than the generation step. That is where the user actually needs help.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Why interaction detail matters more than layout now</title>
      <link>https://allan.ltd/blog/micro-interactions-are-back</link>
      <guid isPermaLink="true">https://allan.ltd/blog/micro-interactions-are-back</guid>
      <pubDate>Mon, 15 Jun 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>design</category>
      <category>craft</category>
      <category>motion</category>
      <description>A model will produce a competent pricing page in seconds, and it will look like every other competent pricing page. What does not come out of the box is how the thing behaves when you touch it.</description>
      <content:encoded><![CDATA[<p>Static layout became a commodity faster than most people expected. Ask for a pricing page, a settings panel, a dashboard shell, and you get a competent one immediately. It will also look approximately like every other competent version of that thing.</p>
<p>Behaviour did not commoditise at the same rate, and the reason is that behaviour is mostly absent from the training data. A screenshot does not record what happened when someone pressed the button.</p>
<h2>The details that carry the difference</h2>
<ul><li>Whether a button acknowledges the press before the network responds. A hundred milliseconds of local feedback removes the entire question of whether the click registered.</li><li>How a list reorders. If items jump, people lose their place and re-scan. If they move, people track them.</li><li>What a panel does at the end of its travel. A small overshoot and settle reads as a physical object. A linear stop reads as a div that changed opacity.</li><li>Whether focus lands somewhere sensible after an action. This is invisible to mouse users and decisive for everyone else.</li></ul>
<h2>The rule that keeps it from becoming decoration</h2>
<p>Motion has to carry information. If the animation does not tell me where something came from, where it went, or that the system heard me, it is decoration, and decoration is the first thing that reads as filler.</p>
<p>The test I use is to describe what the animation communicates in one sentence without using the words smooth, polished or premium. If that sentence does not exist, the animation is spending time and attention for nothing.</p>
<h2>Where the budget should go</h2>
<p>Interaction work is expensive per pixel and cheap per screen, because it concentrates in a handful of components that appear everywhere. Getting the button, the input, the list row and the overlay right covers most of what a user touches in a session.</p>
<p>That is a much better use of a week than adding motion to a marketing page nobody scrolls twice.</p>
<h2>Where to start</h2>
<ul><li>Pick your four most-used components and spend one week on their interaction states only. No new features.</li><li>Add optimistic local feedback to every action that waits on a network call. Press state first, result second.</li><li>Write the one-sentence justification for each existing animation. Delete the ones you cannot write.</li><li>Check what happens to keyboard focus after your three most common actions. This is usually broken and usually a ten-minute fix.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>The production tier of design work is gone</title>
      <link>https://allan.ltd/blog/ai-killed-one-design-job</link>
      <guid isPermaLink="true">https://allan.ltd/blog/ai-killed-one-design-job</guid>
      <pubDate>Tue, 09 Jun 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>careers</category>
      <category>ai</category>
      <category>design</category>
      <description>Not design jobs in general. One specific tier: the work where the brief arrived fully specified and the task was to render it. That tier paid a lot of rent and taught a lot of people their craft.</description>
      <content:encoded><![CDATA[<p>The honest version of the AI and jobs conversation is neither &quot;designers are fine&quot; nor &quot;we are finished&quot;. One clearly identifiable tier of work evaporated, and the rest did not.</p>
<p>The tier where the decisions were already made and the task was execution. Resize this into nine placements. Same layout, different market. Turn these notes into a deck by Thursday.</p>
<h2>Why it went first</h2>
<p>It had the two properties that make work automatable. The input was fully specified, so nothing had to be inferred about intent. And the output was judged against a fixed reference, so correctness was checkable without taste.</p>
<p>Anything with those two properties was going to go. It is worth noticing that the same test predicts what is safe: work where the input is ambiguous and the output is judged against a goal rather than a template.</p>
<h2>The part nobody has solved</h2>
<p>That tier was where juniors learned. Not because the work was educational in itself, but because volume builds pattern recognition. You produce two hundred layouts and you start to see, without being told, why some sit right and some do not.</p>
<p>Remove the volume and the apprenticeship goes with it. The profession has not replaced that mechanism, and most of the advice being given to juniors right now quietly assumes someone else will.</p>
<h2>What partly replaces it</h2>
<p>The closest substitute I have found is structured critique of generated work. Give someone a brief and twenty generated options and ask them to rank and justify. It exercises the same judgement the volume used to build, at higher density and without the tedium.</p>
<p>It is not identical. Producing something teaches things that evaluating it does not. But it is considerably better than nothing, which is the current default.</p>
<h2>Where to start</h2>
<ul><li>If most of your week was production work, pick one project and ask to be in the framing conversation. Not for extra pay. For the record of having done it.</li><li>Start keeping a decisions log. What you recommended, what the alternative was, what happened. That document is what the surviving tier is hired on.</li><li>If you lead a team, replace lost volume work with weekly critique sessions on generated output. Twenty options, ranked, justified out loud.</li><li>Be direct with juniors about which tier their current work sits in. Vague reassurance is worse than a clear map.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Prototyping to make a decision, not to get approval</title>
      <link>https://allan.ltd/blog/prototype-to-decide</link>
      <guid isPermaLink="true">https://allan.ltd/blog/prototype-to-decide</guid>
      <pubDate>Wed, 03 Jun 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>process</category>
      <category>prototyping</category>
      <category>product</category>
      <description>Most prototypes are built to survive a review meeting: perfect data, happy path, nothing that could go wrong while someone senior is watching. They always get approved and they teach nobody anything.</description>
      <content:encoded><![CDATA[<p>There are two kinds of prototype and they are frequently confused. One exists to get permission. The other exists to settle a question. They look similar and they are built completely differently.</p>
<p>The approval prototype has clean data, a single path, no empty states and no failure modes. It is a sales artefact. That is a legitimate thing to need, but it cannot come back with bad news, which means it cannot inform a decision.</p>
<h2>Write the sentence first</h2>
<p>Before building, write the single sentence the prototype is meant to settle. Then check that the sentence has a version you would hate to be true. If it does not, you are building a demo.</p>
<ul><li>&quot;People will paste their existing spreadsheet in rather than start from our template.&quot;</li><li>&quot;Users will not trust an auto-generated summary unless they can see the source.&quot;</li><li>&quot;Onboarding survives someone who arrives with no data at all.&quot;</li></ul>
<p>Each of those can fail, and each failure changes what gets built. That is the whole test.</p>
<h2>Build the ugliest thing that can answer it</h2>
<p>Fidelity should be set by the question, not by the audience. If the question is whether people will paste data in, you need a text box and a parser. You do not need the visual design, and adding it makes the result harder to read, because participants start commenting on the styling.</p>
<p>There is a real trap here now. Generation made polished output nearly free, which makes the beautiful demo more tempting than ever at exactly the moment it became less necessary.</p>
<h2>Ten probes beat one showcase</h2>
<p>The economics changed in favour of breadth. When each probe took three days you could afford one and you made it count. When each takes two hours you can test ten variations of the same question and find where the answer flips.</p>
<p>That is where the leverage from these tools actually is, and most teams are spending it on making a single artefact prettier instead.</p>
<h2>Where to start</h2>
<ul><li>For the next prototype, write the sentence it settles at the top of the file. If you cannot, do not build it yet.</li><li>Deliberately strip the visual design from one research prototype and see whether the feedback gets more useful.</li><li>Budget prototypes in questions, not in screens. Three questions this sprint, not one flow.</li><li>Record the answer somewhere durable, including the ones that killed an idea. Those are the expensive ones to relearn.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Naming design tokens for machine consumers</title>
      <link>https://allan.ltd/blog/your-design-tokens-are-an-api</link>
      <guid isPermaLink="true">https://allan.ltd/blog/your-design-tokens-are-an-api</guid>
      <pubDate>Mon, 01 Jun 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>design-systems</category>
      <category>engineering</category>
      <category>ai</category>
      <description>Tokens used to be an internal convenience. A badly named one cost a moment of squinting. Now agents read them, and a name that describes appearance instead of purpose gets applied wrongly at scale.</description>
      <content:encoded><![CDATA[<p>For most of their history, design tokens were a private convenience. If one was named badly a developer would squint, work out what was meant, and use the right one anyway. The cost was seconds and it was paid by someone who understood the context.</p>
<p>Agents do not squint. They match on the name, and when the name lies the result is applied consistently across everything they touch.</p>
<h2>Appearance names versus purpose names</h2>
<pre data-lang="css"><code>/* Appearance. An agent has to guess the purpose. */
--color-2: #a370ff;
--gray-light-alt: rgba(0,0,0,.06);
--blue-500: #3b82f6;

/* Purpose. Nothing left to infer. */
--color-accent: #a370ff;
--color-border-subtle: rgba(0,0,0,.06);
--color-status-info: #3b82f6;</code></pre>
<p>Same values, very different failure rates. The second set tells a consumer what the token is for. The first only says what it currently looks like, which is exactly the fact that stops being true after a rebrand.</p>
<p>The tell for a bad token name is that you cannot describe when to use it without referring to a colour.</p>
<h2>The tokens nobody can define</h2>
<p>Every mature system accumulates tokens whose purpose nobody remembers. There is usually a --gray-3 and a --gray-alt and a --border-light that resolve to nearly the same value for reasons lost to a redesign three years ago.</p>
<p>These are worse than useless once agents are consuming the system, because they present a choice where no meaningful distinction exists. The model picks arbitrarily and the arbitrariness spreads.</p>
<h2>Renames are breaking changes now</h2>
<p>When humans were the only consumers, a rename was a find-and-replace and a mild inconvenience. With agents in the loop, any cached context, prompt file or generated code referencing the old name keeps producing it long after the rename lands.</p>
<p>Treat a rename the way you would treat renaming a public API method. Keep the old name as a documented alias for a period, mark it deprecated in the docs the agents read, and remove it deliberately rather than opportunistically.</p>
<h2>Where to start</h2>
<ul><li>Export your token list and try to write a one-line &quot;use this when&quot; for each. The ones you cannot write are the ones to fix or delete.</li><li>Find tokens resolving to values within a few percent of each other. Merge or differentiate them explicitly.</li><li>Rename by purpose, starting with the ten tokens used most often. Keep aliases and mark them deprecated.</li><li>Ask an agent to build a small component using only your tokens. Where it reaches for a hard-coded value, your naming has a hole.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>What belongs in a design portfolio now that polish is free</title>
      <link>https://allan.ltd/blog/nobody-cares-about-your-pixels</link>
      <guid isPermaLink="true">https://allan.ltd/blog/nobody-cares-about-your-pixels</guid>
      <pubDate>Tue, 26 May 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>careers</category>
      <category>portfolio</category>
      <category>design</category>
      <description>The visual quality floor rose sharply and made most portfolios indistinguishable. A beautiful final screen now demonstrates something a model does in a minute. It says almost nothing about the person who made it.</description>
      <content:encoded><![CDATA[<p>I have been through a lot of portfolios this year. The average visual quality is higher than it was two years ago and the portfolios have become harder to tell apart, which are the same fact stated twice.</p>
<p>The standard structure is a beautiful hero shot, three device mockups at an angle, a colour palette, and a process diagram with four evenly sized boxes. Nowhere in it is any indication of what was difficult.</p>
<h2>Why polished outcomes stopped being evidence</h2>
<p>A portfolio is a claim about future performance. It works when the artefact is hard to produce without the underlying skill, so the artefact stands in as proof.</p>
<p>That link weakened. A polished screen no longer proves the person can produce polished screens under real constraints, because the same screen can be generated by someone who cannot. The proof has to move to something that did not get cheaper.</p>
<h2>What did not get cheaper</h2>
<ul><li>The constraint that made the obvious solution impossible, and what you did about it. Legal, technical, a deadline, an existing system you could not change.</li><li>The version you shipped and then killed. What you saw in the data, how long you left it, what it cost.</li><li>The thing the client asked for that you talked them out of, and the argument that worked.</li><li>What you would do differently, specifically, with a number attached.</li></ul>
<p>All four are records of judgement under pressure. None can be generated, because none of them are visible in the output. They only exist if you were actually there.</p>
<h2>The format that carries this</h2>
<p>Long case studies with a linear narrative tend not to get read. What works better is one page per project with the constraint stated first, the decision second, the outcome third, and the screens as supporting evidence rather than the headline.</p>
<p>It reads faster and it answers the question the reviewer actually has, which is whether you can be trusted with an ambiguous problem.</p>
<h2>Where to start</h2>
<ul><li>Take your strongest project and write the constraint that shaped it in two sentences. If you cannot find one, that project is decoration.</li><li>Add one thing you got wrong to each case study, with what it cost and what you changed. This is the single highest-signal element in a portfolio.</li><li>Move the screens below the reasoning. Let them support the argument instead of being it.</li><li>Start writing decisions down as you make them. Reconstructing them two years later produces a tidy story that is usually false.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Moving a studio off hourly billing: what broke</title>
      <link>https://allan.ltd/blog/we-stopped-selling-hours</link>
      <guid isPermaLink="true">https://allan.ltd/blog/we-stopped-selling-hours</guid>
      <pubDate>Tue, 19 May 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>agency</category>
      <category>business</category>
      <category>process</category>
      <description>Around 38% of agencies have shifted at least one service line off hourly. The advice is right. The difficulty is undersold, and it lands in one specific place that nobody warns you about.</description>
      <content:encoded><![CDATA[<p>Around 38% of agencies have now moved at least one service line off hourly billing. Having done it, I would say the recommendation is correct and the transition is harder than the people recommending it tend to admit.</p>
<h2>What improved immediately</h2>
<p>Efficiency stopped being self-defeating. Under hourly, every improvement we found reduced revenue on the same piece of work, which is a strange thing to build a business on. Under outcome pricing, the gain is ours to keep.</p>
<p>The conversation with clients also changed shape. It moved from how many hours this will take to what it is worth having, and the second conversation is better in every respect. Clients engage with it more seriously and it surfaces disagreements about value early rather than at invoice time.</p>
<h2>What broke</h2>
<p>All of the estimation risk moved onto us, and it concentrated in one place: scope ambiguity.</p>
<p>On hourly, a vague scope is the client's problem. They pay for the exploration as it happens and nobody has to be right up front. On a fixed outcome, a vague scope comes directly out of margin, and you discover the size of the mistake in week five when it is too late to reprice without damaging the relationship.</p>
<p>We lost money on two projects learning this. In both cases the estimate was reasonable for the project we thought we had agreed to.</p>
<h2>The fix was not better estimating</h2>
<p>We tried that first. More detailed breakdowns, historical averages, padding. The estimates got more confident and roughly as wrong, because the error was never in the arithmetic. It was in not knowing what we were agreeing to.</p>
<p>What worked was making discovery its own paid engagement, small and bounded, whose only deliverable is a written scope both sides sign. Two weeks, fixed fee, and the project proper is quoted afterwards against that document.</p>
<p>It sounds bureaucratic. It is the single change that made the model survivable, because it moves the guessing to the point where being wrong is cheap for everyone.</p>
<h2>The thing to keep doing anyway</h2>
<p>Keep tracking hours internally even after you stop billing them. It is the only way to know whether an outcome price was right, and without it you are pricing on feel within about six months.</p>
<h2>Where to start</h2>
<ul><li>Pick the service line you have delivered most often and price it as an outcome. History gives you the real cost.</li><li>Write a discovery offer before you need it: fixed fee, fixed duration, signed scope as the deliverable.</li><li>Put the change mechanism in the contract. Out-of-scope work gets quoted, never absorbed silently.</li><li>Keep internal time tracking. Review outcome prices against actuals every quarter.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>The limits of adaptive interfaces</title>
      <link>https://allan.ltd/blog/personalized-doesnt-mean-good</link>
      <guid isPermaLink="true">https://allan.ltd/blog/personalized-doesnt-mean-good</guid>
      <pubDate>Thu, 14 May 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>ux</category>
      <category>ai</category>
      <category>product</category>
      <description>Personalisation is the trend of the year and it has a failure mode that rarely makes it onto the slide. When an interface reshapes itself per person, it stops being something two people can talk about.</description>
      <content:encoded><![CDATA[<p>Adaptive interfaces are genuinely useful and the case for them is easy to make. The case against is more specific and it only shows up after launch, usually in support tickets.</p>
<p>When the interface reshapes itself for each person, it stops being a shared object. That sounds abstract until you list what depends on it being shared.</p>
<h2>What breaks when the layout is personal</h2>
<ul><li>Support cannot walk someone through a screen they cannot see. Every call starts with reconstructing what the user is looking at.</li><li>Colleagues cannot give directions. &quot;It is in the third tab&quot; stops being true, and in team products this is constant.</li><li>Documentation describes a layout that may not exist for the reader, and screenshots go stale in a way you cannot detect.</li><li>Muscle memory never forms, because the target keeps moving. For daily-use tools this is a real productivity cost.</li></ul>
<blockquote><p>A predictable interface is a feature. Every rearrangement spends trust you may not get back.</p></blockquote>
<h2>The distinction that makes it work</h2>
<p>The useful split is between payload and furniture.</p>
<p>Payload is content and defaults. What is in the list, what is pre-filled, what is surfaced first, which of forty settings you see at the top. Personalising these is almost always positive and it is invisible in the bad way, which is to say nobody notices it working.</p>
<p>Furniture is structure. Navigation, the location of primary actions, the shape of the page. Personalising these usually costs more than it returns, because the gain is a few seconds of scanning and the loss is every property in the list above.</p>
<h2>If you must move the furniture</h2>
<p>Sometimes the case is strong enough. When it is, make the change explicit rather than silent. Let the user see that something moved, tell them why, and give them a way back to the default. Silent rearrangement is what produces the feeling that the software is unreliable.</p>
<h2>Where to start</h2>
<ul><li>Audit what your product currently personalises and sort each item into payload or furniture. Most teams have not made this distinction explicitly.</li><li>For anything in the furniture column, ask what the support call sounds like. If you cannot answer, that is the answer.</li><li>Add a visible reset to default for any adaptive structure you keep.</li><li>Check whether your own documentation still matches what a new user sees. If it does not, the personalisation is already costing you.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Why small senior teams now ship like large ones</title>
      <link>https://allan.ltd/blog/small-team-shouldnt-ship-like-this</link>
      <guid isPermaLink="true">https://allan.ltd/blog/small-team-shouldnt-ship-like-this</guid>
      <pubDate>Thu, 07 May 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>agency</category>
      <category>ai</category>
      <category>process</category>
      <description>The gap between what three senior people deliver and what fifteen deliver has narrowed sharply. The cause is not that individuals got faster. It is that the coordination work justifying the larger team mostly disappeared.</description>
      <content:encoded><![CDATA[<p>Most of what justified a large project team was never the work itself. It was coordination: specifications written precisely enough that one group could hand something to another, meetings to resolve what the specification left ambiguous, and rework when it turned out ambiguous anyway.</p>
<p>That overhead grows with the number of handoffs, not with the size of the problem. Which is why adding people past a certain point stops helping.</p>
<h2>What changed</h2>
<p>The last honest argument for splitting design and build was that no single person could hold both ends of a real product. Design required depth in one set of tools, implementation in another, and the switching cost was high enough that specialisation won.</p>
<p>That cost dropped. A designer who can describe what they want in enough detail can now get a working implementation to react to, which collapses the longest handoff in the process into a conversation with themselves.</p>
<h2>What this does not mean</h2>
<p>It does not mean headcount is obsolete, and anyone telling you that is selling something. Scale still needs people. Operating a product used by millions is a different discipline from building one, and it is not a discipline that compresses.</p>
<p>What changed is the minimum viable team for a serious product, which got much smaller, while the coordination overhead of a large one stayed exactly where it was.</p>
<h2>The question to ask a potential partner</h2>
<p>Stop counting people. Ask how many hands the work passes through between the decision and the deploy.</p>
<p>That number predicts your timeline better than the size of the org chart, and it is a question most agencies have never been asked, which makes the answer informative in itself.</p>
<h2>Where to start</h2>
<ul><li>Map your last shipped feature as a chain of handoffs. Count them. That count is your real cycle time driver.</li><li>Find the handoff that generates the most clarifying questions and try collapsing it into one person for the next feature.</li><li>When briefing an external team, ask the handoff-count question directly and see whether they can answer it.</li><li>Resist adding people to a late project. It has never worked and the coordination maths got worse, not better.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>The visual signature of generated work, and how to break it</title>
      <link>https://allan.ltd/blog/ai-slop-has-a-look</link>
      <guid isPermaLink="true">https://allan.ltd/blog/ai-slop-has-a-look</guid>
      <pubDate>Thu, 30 Apr 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>design</category>
      <category>ai</category>
      <category>craft</category>
      <description>Users cannot articulate what is wrong with the page. They just trust it slightly less. The tells are consistent enough to list, and none of them are mistakes, which is what makes them hard to argue about.</description>
      <content:encoded><![CDATA[<p>Generated work has settled into a house style, and enough people have now seen enough of it that it reads instantly. Including people who could not name a single thing about typography and would not describe themselves as design-literate.</p>
<p>What they report is not &quot;this looks generated&quot;. It is a small drop in trust they cannot explain, which is a harder problem, because you cannot fix a complaint nobody can articulate.</p>
<h2>The tells</h2>
<ul><li>Three feature cards. Always three, always identical visual weight, because balance is the default and choosing what matters is not.</li><li>Gradient treatment on a headline that is not the most important thing on the page. Emphasis applied evenly is emphasis applied to nothing.</li><li>Copy that is grammatical, on topic and says nothing. It survives a read-through and leaves no residue.</li><li>Icons from four different visual languages sharing one row. Each was individually reasonable.</li><li>Spacing that is consistent everywhere and hierarchical nowhere. Everything breathes equally, so nothing leads.</li></ul>
<h2>Why competence became the signal</h2>
<p>None of those are errors, which is the difficulty. Every one would pass a review. The common thread is the absence of a decision: each element is the safe average of what that element usually looks like.</p>
<p>Human work carries evidence of choices, including slightly odd ones. A section that is deliberately cramped because it is less important. A photograph that is not quite polished because it is real. Those cost something to produce, which is exactly why they register as authentic.</p>
<h2>The cheapest fix</h2>
<p>One deliberate, specific choice per page that a model would not have volunteered. Not five. One is enough to change how the whole page reads.</p>
<ul><li>A real photograph of a real thing, even an imperfect one.</li><li>One sentence in a recognisably human voice, ideally with a specific detail in it.</li><li>An element that breaks the grid because the content earned it.</li><li>Unequal weighting between the three cards, because one of them actually is more important.</li></ul>
<h2>Where to start</h2>
<ul><li>Open your highest-traffic page and count how many elements have equal visual weight. Then decide which one should win.</li><li>Find the most generic sentence on the page and replace it with something only your team could have written.</li><li>Replace one stock image with a real photograph, even a worse one.</li><li>Ask someone outside the team which part of the page they trust least. They will usually point straight at the generated section without knowing why.</li></ul>]]></content:encoded>
    </item>
    <item>
      <title>Design handoff: the specification was never the problem</title>
      <link>https://allan.ltd/blog/the-handoff-was-never-the-problem</link>
      <guid isPermaLink="true">https://allan.ltd/blog/the-handoff-was-never-the-problem</guid>
      <pubDate>Thu, 23 Apr 2026 00:00:00 GMT</pubDate>
      <dc:creator>Allan Leone</dc:creator>
      <category>process</category>
      <category>design-systems</category>
      <category>engineering</category>
      <description>A decade of tools promised to fix design-to-development handoff, and they largely did fix the file transfer. Builds still come back wrong, because the thing that was missing was never in the file.</description>
      <content:encoded><![CDATA[<p>Handoff tooling is genuinely good now. Specifications are exact, tokens export cleanly, and an engineer can pull real values in seconds without asking anyone. The problem the tools set out to solve is solved.</p>
<p>Builds still come back wrong. Not because someone misread a margin, but because the file described one state of a system that has dozens.</p>
<h2>What was never in the mockup</h2>
<ul><li>What happens when that name is eighty characters long, or two characters long.</li><li>What the list looks like empty, and with ten thousand rows.</li><li>Which of these two things wins when both conditions are true at once.</li><li>What the user sees while it loads, and what they see when it fails.</li><li>Whether the action is reversible, and what undo means if it is.</li></ul>
<p>That information existed. It lived in the designer's head and it transferred by proximity: a conversation, a Slack thread, someone leaning over a desk at the right moment. The mockup was never the specification. It was a prompt for a conversation that happened around it.</p>
<h2>Why this is getting worse</h2>
<p>Two things changed at once. Distributed teams removed a lot of the proximity, and now agents are consuming the specification too.</p>
<p>An engineer who receives an underspecified design asks a question or makes a judgement call informed by knowing the product. An agent does neither. It picks something plausible and implements it consistently, which means the gap in the spec becomes a pattern in the codebase rather than a single bug.</p>
<h2>The artefact that fixes it</h2>
<p>Not a longer document. A short list attached to each screen covering the states that are not drawn: empty, loading, error, maximum content, minimum content, and what is irreversible.</p>
<p>Six lines per screen. It takes about ten minutes and it is the part of the handoff that was always doing the real work, just informally.</p>
<h2>Where to start</h2>
<ul><li>Add the six-state list to the next screen you hand over. Empty, loading, error, max content, min content, irreversible actions.</li><li>Look at the last three build discrepancies your team had. Ask whether the information was in the file or in someone's head.</li><li>Put the edge cases in the same place as the design, not in a separate document nobody opens.</li><li>If agents are writing your components, treat the states list as required rather than optional. It is now the difference between one wrong screen and forty.</li></ul>]]></content:encoded>
    </item>
  </channel>
</rss>
