What rebuilding the Lesse Studio website taught us about self-hosting, performance, and choosing tools with intention.
What rebuilding the Lesse Studio website taught us about self-hosting, performance, and choosing tools with intention.
Designing for agentic AI requires attention to both the system’s behavior and the transparency of its actions. Between the black box and the data dump lies a more thoughtful approach. Victor Yocco explores how to map decision points and reveal the right moments to build trust through clarity, not noise.
# CLAUDE.md - Always write production grade code. - Never introduce a regression. - Be thorough, consider edge cases. Three rules. None of them will ever fire. Not because the agent is lazy. None of them are instructions. They are wishes wearing the costume of rules. I work inside a setup with a large rule library and enough observability to see which rules fire and which sit there as decoration. That gap is wide. Most rules read like aspiration. A few read like physics. After watching a lot of them hold and a lot of them rot, the failures land in five clean categories. If your agent keeps ignoring your own instructions, your rule is almost certainly one of these. 1. Aspiration with no edge "Be thorough." "Write quality code." "Handle errors properly." Read one out loud and ask a simple question. What would it look like to violate it. If you cannot answer in one sentence, the agent cannot either. A rule the model cannot fail is a mood. It nods at the line and moves on, because nothing concrete exists to obey. Repairing this takes one testable sentence. A line you can hold against a diff and answer yes or no. 2. No trigger This one is specific enough to obey. It still fails. "Use the new auth pattern." When. On every file. Only auth files. Only new code. Only when touching login. Nothing in the rule says, so the agent guesses. Sometimes it guesses right. Sometimes it does not. You read that as the agent being unreliable. It is the rule staying silent about its own moment. Every real instruction carries a trigger, the condition that wakes it up. Strip that trigger and the rule fires at random, which from the outside looks identical to the rule being ignored. 3. No enforcement Now your rule is specific and it carries a clear trigger. It still breaks on the long sessions. Only one thing is holding it up, the agent remembering it. Early in a session, with the rule fresh in context, compliance looks perfect. Two hours in, after the context has been squeezed and rebuilt, that rule is a faint memory competing with a hundred others. Memory does not enforce anything. A rule that lives only in the model's attention degrades exactly when you need it most, on the long, tired, high stakes session. A durable rule has a backstop. Something outside the model that notices the miss and says no. What that backstop is matters less than the fact that one exists. 4. Contradiction with no precedence Two rules. Both correct. They disagree. One says move fast and keep changes small. Another says add a test for every new behavior. On a one line fix, which wins. If your rules do not say, the agent obeys whichever it noticed last. That is a coin flip with extra steps, dressed as a decision. Contradiction is fine. Real systems carry competing goals. What is missing is precedence, a stated order so the tie resolves the same way every time, instead of depending on which rule landed closest to the cursor. 5. Stale reference This is the worst one, because it used to work. Your rule names a file, a function, a flag, a path. Then the thing moves. Gets renamed. Gets deleted. The instruction does not move with it. Now it points at nothing, or worse, at whatever took the old name. A rule that lies does more damage than a rule that is missing. A missing rule fails open and you notice. A stale rule fails confident. It sends the agent at the wrong target with full authority, and the green log hides it. Every rule that names a specific artifact carries a small debt. Each time that artifact moves, the line turns into misinformation unless something updates it in the same motion. What sits under all five Sharpen the pattern and the five collapse into one test. What makes this rule fire, and what catches it when it does not. A rule with no answer to both halves is aspiration. It will shine in the demo and rot in production. A rule with an answer to both is closer to physics. It holds when the session runs long and the context runs tight and nobody is watching. Most CLAUDE.md files I read are ninety percent aspiration in the costume of physics. Honesty fixes more of this than better sentences do. Be clear about which of your rules can fire, and accept that the rest are notes to yourself. Notes to yourself are fine. Calling them rules is how a file slowly stops meaning anything, one ignored line at a time. Your turn Open your own CLAUDE.md or agent rules right now. Pick one rule and run the two questions on it. What makes it fire, what catches the miss. Then tell me which of the five your weakest rule falls into. I am curious which one bites hardest in the wild, because in my own library it is number three.
Design always starts with function — function shapes form. But if that function can’t be made completely invisible and people still have to interact with it, it inevitably becomes part of their experience. In this article, Kyrylo Levashov shares four common software design assumptions.
Accessibility works best when it blends into everyday design workflows. The goal isn’t a big transformation, but simple work processes that fit naturally into a team’s routine. With Figma variables, testing font size increases becomes part of the design flow itself, making accessibility feel almost inevitable rather than optional.
Every high-resolution hero image, autoplay video, and complex JavaScript animation carries a cost. Sustainable UX challenges the era of “unlimited pixels” and reframes performance as responsibility. In 2026, truly sophisticated design is defined not by how much it adds, but by how thoughtfully it reduces its footprint.
Highlights James enabled adaptive autofill in Nightly for testing, which we believe should provide better results in the URL bar when doing autocomplete! Jack updated the illustrations shown on some of our error pages to match the latest approved designs, giving users more polished artwork when the browser encounters connection or security errors! Controls for the Memories feature can now be set during Smart Window onboarding We’ve disabled the CSS filter implicitly applied to WebExtension pageAction SVG icons across all release channels starting in Firefox 152, completing the deprecation NOTE: The blog post published at WebExtensions API changes in Firefox 149-152 provides to extensions developers more details about this deprecation and links to the related MDN docs. Friends of the Firefox team Resolved bugs (excluding employees) Script to find new contributors from bug list Volunteers that fixed more than one bug Amin Amir Pranjali Srivastava Sam Johnson New contributors (🌟 = first patch) 🌟:23rd: Regression: The new swipe-to-navigation indicator stucks for a moment, when deciding not to navigate the other page 🌟Akeem Omosanya: Remove commented-out code in SearchService.sys.mjs Amin Amir: 🌟Fix browsingContext.sys.mjs to assign to #contextCreatedHandled instead of contextCreatedHandled Fix missing WITHOUT ROWID SQLite performance optimization in SERPCategorization.sys.mjs 🌟Sahaj: Suggest the default target language for translation after changing the detected source language 🌟JIANG Zhirui: Breakpad build failed on Windows using VS2026 due to removal of stdext John Iweh: Add “Open in New Tab” and “Open in New Container Tab” options to the context menu for Tabs from Other Devices Jak: Bookmarks and History – should respect the “When you open a link, image or media in a new tab, switch to it immediately” setting 🌟Andy [:rgbcmy]: Autoplayed next video should also be PIP konyhéa: “Escape” key should collapse the expanded on hover sidebar launcher even if hover is still active. Pranjali Srivastava: Remove icon property from sidebar extensions Show language-agnostic SelectTranslations context menu item when the source and target languages are the same Project Updates Add-ons / Web Extensions Addon Manager & about:addons Fixed long-standing regression on the autocomplete and datalist popups for extension inline options pages on about:addons (introduced in Firefox 68 by Bug 1532724, fix shipping in Firefox 152) – Bug 1595158 WebExtensions Framework Fixed access to web-accessible resources declared with <all_urls> from sandboxed documents (null-principal URLs), restoring extension redirects from the context-menu search flow, starting in Firefox 152 – Bug 2033905 WebExtension APIs Added exhaustive test coverage for tabs.move() against additional edge cases related to split-view tabs – Bug 2029092 DevTools Andreas Farre improved the Session History tab in the Application panel (still behind devtools.application.sessionHistory.enabled) added support for remote debugging (#2014064, #2016121) made sure that calls to History.replaceState are reflected in the UI (#2037359) Julian Descottes [:jdescottes] fixed the most frequent DevTools crash we were observing in Telemetry, adding a guard against IDBTransaction errors when retrieving breakpoints in the Debugger (#2030260) Nicolas Chevobbe [:nchevobbe] fixed the image preview tooltip for relative URLs images in constructed stylesheet (#2035503) Julian Descottes [:jdescottes] reduced the overhead we had because of network requests monitoring by only decoding response content when the user actually want to see the response (#2026228) WebDriver Amin Amir cleaned up an incorrect variable assignment in our browsingContext module. Logan Rosen updated stale references and broken links in our documentation about Marionette. Sameem improved the Marionette and WebDriver BiDi screenshot commands to enforce maximum allowed dimensions. Leo McArdle fixed the regression in the “log.entryAdded” event, which lacked an error message in the “text” field for the messages of type “error”. Henrik Skupin fixed an issue in Marionette where WebDriver:Navigate and WebDriver:Refresh did not handle errors when the underlying navigation failed. Henrik Skupin improved geckodriver to detect an early Firefox exit during startup on Android, avoiding up to 60 seconds of unnecessary connection attempts. Henrik Skupin updated the geckodriver CI build job to produce a universal macOS binary supporting both x64 and aarch64. Lint, Docs and Workflow Sylvestre ported some linters (e.g. file-whitespace, test-manifest-toml, license, file-perm, rejected-words & more) to Rust to help improve the runtime of the code review bot. Dale has been working on migration to moz-src for customkeys, dom/quota and odom/geolocation https://arewemozsrcyet.com/ New Tab Page We did our first region-specific trainhop on May 11th (just 15% of the US), and turned on HNT Nova (and sometimes Widgets) for those clients to get some advance-data of its behaviour in the wild! A note that HNT Nova gets turned on for everybody when Firefox 151 ships on May 19th. We’ll be launching a similar experiment in the DE, probably on May 12th, also at 15% population. Most of the team is heads down building out a sports-tracking widget, attempting to get that ready in time to be generally available for the upcoming World Cup event. Dre landed a new world clock widget, which is currently off by default, but pretty snazzy! Search and Urlbar Nova (URL Bar Design Refresh) Drew and Daisuke continued their work on Nova styling for the Address bar (input and view). Search and Suggest Drew finalized two bugs for World Cup and sports suggestions, which were landed and uplifted: one to update the localization string for scheduled games and another to show both teams’ icons in suggestions. Drew also landed and uplifted a fix for rich search suggestion icons being forced into a square aspect ratio. Standard8 updated Ecosia favicons to the latest branding, including QA testing and publishing. Settings Redesign (SRD) Stephanie landed a test to ensure search suggestion settings are hidden when quicksuggest is disabled, as well as a patch to resolve TypeScript issues in search.mjs, and is adding test coverage to confirm removed search engines are not displayed in the default engines dropdown. General URL Bar and Component Updates Daisuke landed implementation of the context menu on URL bar results, and a fix to show the loading URL in the URL bar when starting up with a homepage. Marco is working on several tasks, including a PDF download / focus stealing issue and allowing arrays to be bound in Sqlite.sys.mjs. Marco also worked on fixes related to Places, such as avoiding replacing the favicons database if it is not corrupt. Standard8 finalized the URL bar test manifest split. Standard8 also upgraded us to TypeScript 6. Moritz landed a fix for URL bar abandonment telemetry being recorded when clicking an engine in the unified search button popup (Bug 2032973), which was also uplifted. Moritz also simplified search mode switcher item activation in tests, and made it so that the unified search button popup closes when installing an open search engine. Smart Window natural language starting with tab close/undo 2035343 with expandable action log 2031508 assistant rendering feedback up/down 2032994 and markdown table 2027029 nova styling blur 2027877 and suggestions 2026823 accessibility screen reader 2028676 and keyboard focus 2037565 optimize conversation starters extra requests 2030005 and caching 2033430 Storybook/Reusable Components/Acorn Design System Nova token updates occasionally, focused on SRD UX Fundamentals Added support for the “SEC_ERROR_CA_CERT_INVALID” certificate error to the Felt Privacy error pages. – 2035942 Settings Redesign Settings redesign is being tested and will hopefully go out in Firefox 152!