Latest Posts (8 found)
Den Odell 2 weeks ago

HTML’s Best Kept Secret: The <output> Tag

Every developer knows . It’s the workhorse of the web. But ? Most have never touched it. Some don’t even know it exists. That’s a shame, because it solves something we’ve been cobbling together with s and ARIA for years: dynamic results that are announced to screen readers by default. It’s been in the spec for years. Yet it’s hiding in plain sight . Here’s what the HTML5 spec says: The element represents the result of a calculation performed by the application, or the result of a user action. It’s mapped to in the accessibility tree . In plain terms, it announces its value when it changes, as if it already had . In practice, that means updates do not interrupt the user. They are read shortly after, and the entire content is spoken rather than just the part that changed. You can override this behavior by setting your own ARIA properties if needed. Usage is straightforward: That’s it. Built-in assistive technology support. No attributes to memorize. Just HTML doing what it was always meant to do. I discovered on an accessibility project with a multi-step form. The form updated a risk score as fields changed. It looked perfect in the browser, but screen reader users had no idea the score was updating. Adding an ARIA live region fixed it. But I’ve always believed in reaching for semantic HTML first, and live regions often feel like a patch. That’s when I scoured the spec and jumped out. It understands forms without requiring one, and it announces its changes natively. Turns out the simplest fix had been in the spec all along. Because we forgot. It’s not covered in most tutorials. It doesn’t look flashy. When I searched GitHub public repos, it barely showed up at all. It gets overlooked in patterns and component libraries too. That absence creates a feedback loop: if no one teaches it, no one uses it. Like , has a attribute. Here you list the s of any elements the result depends on, separated by spaces: For most users, nothing changes visually. But in the accessibility tree it creates a semantic link, letting assistive technology users connect the inputs with their calculated result. It doesn’t require a either. You can use it anywhere you are updating dynamic text on the page based on the user’s input. By default is inline, so you’ll usually want to style it for your layout, just as you would a or . And because it has been part of the spec since 2008, support is excellent across browsers and screen readers. It also plays nicely with any JavaScript framework you might be using, like React or Vue. Update 7 Oct 2025 : Some screen readers have been found not to announce updates to the tag, so explicitly emphasising the attribute might be worthwhile for now until support improves: . One thing to note: is for results tied to user inputs and actions, not global notifications like toast messages. Those are better handled with or on a generic element, since they represent system feedback rather than calculated output. So what does this look like in practice? I’ve personally reached for in multiple real-world projects since discovering it: During a recent 20-minute coding challenge, I used to display calculation results. Without adding a single ARIA role, the screen reader announced each result as it updated. No hacks required. At Volvo Cars, we displayed user-friendly versions of slider values. Internally the slider might hold , but the output showed . We wrapped the slider and in a container with and a shared label, creating a cohesive React component: I found that password strength indicators and real-time validation messages work beautifully with . The tag even fits modern patterns where you might fetch prices from APIs, show tax calculations, or display server-generated recommendations. Here, a shipping cost calculator updates an tag, informing users once the cost has been calculated: There’s something satisfying about using a native HTML element for what it was designed for, especially when it makes your UI more accessible with less code. might be HTML’s best kept secret, and discovering gems like this shows how much value is still hiding in the spec. Sometimes the best tool for the job is the one you didn’t even know you had. Update 11 Oct 2025 : The ever-excellent Bob Rudis has produced a working example page to support this post. Find it here: https://rud.is/drop/output.html

0 views
Den Odell 1 months ago

Code Reviews That Actually Improve Frontend Quality

Most frontend reviews pass quickly. Linting's clean, TypeScript's happy, nothing looks broken. And yet: a modal won't close, a button's unreachable, an API call fails silently. The code was fine. The product wasn't . We say we care about frontend quality. But most reviews never look at the thing users actually touch. A good frontend review isn't about nitpicking syntax or spotting clever abstractions. It's about seeing what this code becomes in production. How it behaves. What it breaks. What it forgets. If you want to catch those bugs, you need to look beyond the diff. Here's what matters most, and how to catch these issues before they ship: When reviewing, start with the obvious question: what happens if something goes wrong? If the API fails, the user is offline, or a third-party script hangs, if the response is empty, slow, or malformed, will the UI recover? Will the user even know? If there's no loading state, no error fallback, no retry logic, the answer is probably no . And by the time it shows up in a bug report, the damage is already done. Once you've handled system failures, think about how real people interact with this code. Does reach every element it should? Does close the modal? Does keyboard focus land somewhere useful after a dialog opens? A lot of code passes review because it works for the developer who wrote it. The real test is what happens on someone else's device, with someone else's habits, expectations, and constraints. Performance bugs hide in plain sight. Watch out for nested loops that create quadratic time complexity: fine on 10 items, disastrous on 10,000: Recalculating values on every render is also a performance hit waiting to happen. And a one-line import that drags in 100KB of unused helpers? If you miss it now, Lighthouse will flag it later. The worst performance bugs rarely look ugly. They just feel slow. And by then, they've shipped. State problems don't always raise alarms. But when side effects run more than they should, when event listeners stick around too long, when flags toggle in the wrong order, things go wrong. Quietly. Indirectly. Sometimes only after the next deploy. If you don't trace through what actually happens when the component (or view) initializes, updates, or gets torn down, you won't catch it. Same goes for accessibility. Watch out for missing labels, skipped headings, broken focus traps, and no live announcements when something changes, like a toast message appearing without a screen reader ever announcing it. No one's writing maliciously; they're just not thinking about how it works without a pointer. You don't need to be an accessibility expert to catch these basics. The fixes aren't hard. The hard part is noticing. And sometimes, the problem isn't what's broken. It's what's missing. Watch out for missing empty states, no message when a list is still loading, and no indication that an action succeeded or failed. The developer knows what's going on. The user just sees a blank screen. Other times, the issue is complexity. The component fetches data, transforms it, renders markup, triggers side effects, handles errors, and logs analytics, all in one file. It's not technically wrong. But it's brittle. And no one will refactor it once it's merged. Call it out before it calcifies. Same with naming. A function called might sound harmless, until you realize it toggles login state, starts a network request, and navigates the user to a new route. That's not a click handler. It's a full user flow in disguise. Reviews are the last chance to notice that sort of thing before it disappears behind good formatting and familiar patterns. A good review finds problems. A great review gets them fixed without putting anyone on the defensive. Keep the focus on the code, not the coder. "This component re-renders on every keystroke" lands better than "You didn't memoize this." Explain why it matters. "This will slow down typing in large forms" is clearer than "This is inefficient." And when you point something out, give the next step. "Consider using here" is a path forward. "This is wrong" is a dead end. Call out what's done well. A quick "Nice job handling the loading state" makes the rest easier to hear. If the author feels attacked, they'll tune out. And the bug will still be there. What journey is this code part of? What's the user trying to do here? Does this change make that experience faster, clearer, or more resilient? If you can't answer that, open the app. Click through it. Break it. Slow it down. Better yet, make it effortless. Spin up a temporary, production-like copy of the app for every pull request. Now anyone, not just the reviewer, can click around, break things, and see the change in context before it merges. Tools like Vercel Preview Deployments , Netlify Deploy Previews , GitHub Codespaces , or Heroku Review Apps make this almost effortless. Catch them here, and they never make it to production. Miss them, and your users will find them for you. The real bugs aren't in the code; they're in the product, waiting in your next pull request.

0 views
Den Odell 2 months ago

We Keep Reinventing CSS, but Styling Was Never the Problem

We’ve been building for the web for decades. CSS has had time to grow up, and in many ways, it has. We’ve got scoped styles, design tokens, cascade layers, even utility-first frameworks that promise to eliminate bikeshedding entirely. And yet, somehow, every new project still begins with a shrug and the same old question: “So… how are we styling things this time?” It’s not that we lack options. It’s that every option comes with trade-offs. None of them quite fit. We keep reinventing CSS as if it’s the root cause. It isn’t. It’s easy to forget what CSS was originally designed for: documents. You’d write some HTML, style a few headings and paragraphs, maybe float an image to the left, and call it a day. In that world, global styles made sense. The cascade was helpful. Inheritance was elegant. Fast-forward a couple of decades and we’re building highly interactive, component-based, state-driven, design-system-heavy applications, still with a language meant to style a résumé in the early 2000s. CSS wasn’t built for encapsulated components. It wasn’t built for dynamic theming or runtime configuration or hydration mismatches. So we’ve spent years bolting on strategies to make it work. What we have now is a landscape of trade-offs. Each approach solves something. None solve everything. Yet we keep framing them as silver bullets, not as trade-off tools. Here’s the uncomfortable truth: most of our styling pain doesn’t come from CSS itself . It comes from trying to shoehorn CSS into frontend architectures that weren’t designed to support it. React , Vue , Svelte . They all put components at the core. Scoped logic. Scoped templates. Scoped state. Then we hand them a stylesheet that’s global, cascading, and inherited by default. We’ve spent the last decade asking CSS to behave like a module system. It isn’t one. This isn’t just a tooling choice. It’s a question of what trade-offs you’re prepared to live with. Do you want: There’s no single solution. Just strategies. Just context. Styling the web isn’t solved. It may never be. But it gets easier when we stop pretending there’s a perfect answer just one abstraction away. Be clear about what matters, and deliberate about what you’re willing to trade. Because at the end of the day, no one writes perfect CSS. Just CSS that’s good enough to ship. BEM gives you naming predictability, and very verbose selectors. CSS Modules give you scoping, unless you need runtime theming . Utility-first CSS (like Tailwind ) enables fast iteration, but clutters your markup. CSS-in-JS offers colocation and flexibility, at the cost of runtime performance and complexity. Cascade Layers and give you more control, if your team is ready to learn them. Scoped styles with minimal tooling? Use CSS Modules and accept limited runtime flexibility. Predictability and no cascade? Use utility-first CSS and brace for cluttered markup. Dynamic styles colocated with logic? Use CSS-in-JS and monitor your bundle size closely.

0 views
Den Odell 2 months ago

The Web Is About to Get Better for Everyone, Everywhere

The next big thing in web development isn’t a framework. It’s a piece of legislation. Starting summer 2025, the European Accessibility Act will require digital products provided in the EU to meet actual, enforceable accessibility standards. Not "we added some alt text" accessibility. Real accessibility. The kind you can be sued over. And that means the internet is about to get a lot more usable. Turns out “do the right thing” works better when it’s legally enforced. On paper, the EAA is about protecting the rights of disabled users in the EU. In practice, it will quietly upgrade the user experience for everyone, everywhere. Because global companies don’t build fifty different versions of their site. They build one. And when that one needs to pass strict accessibility checks in Europe, it becomes the new default for everyone. Not because they’ve had a sudden ethical awakening, but because it’s cheaper than maintaining a fork. I’ve seen this happen firsthand. At Volvo Cars, I helped lead accessibility work on a complex finance interface used across dozens of countries. Some markets had legal requirements. Others didn’t. We didn’t build two versions. We built one good one. That’s what’s about to happen at scale. We’ve been here before. The GDPR forced companies to rethink privacy. Cookie banners popped up everywhere, and data practices changed, even in countries that had no such law. The EAA will have the same ripple effect. But where GDPR mostly lives in popups and policy pages, accessibility lives in your codebase. This time, it’s going to affect how teams design, build, and ship products. Developers will need to stop misusing s and start writing semantic markup. They’ll have to test keyboard navigation and make sure screen readers can do more than guess. Designers will need to think about contrast, focus indicators, and interaction patterns that work for more than just perfect eyesight and fine motor control. Product managers will need to bring accessibility forward in the roadmap, instead of leaving it to sprint eleven. For teams that never took it seriously, this will feel like a lot. Because it is. The good news is, once companies start updating their design systems and components to comply, those updates don’t stay locked inside. They spread. When Figma kits, React libraries, or UI frameworks adjust for accessibility, thousands of developers benefit, even if they’ve never heard of the EAA. Small teams and solo devs inherit improvements without lifting a finger. Your bootstrapped SaaS gets better because someone at a bank had to follow the law. And just like GDPR influenced privacy legislation far beyond Europe, the EAA could nudge other governments into action. The US has had the ADA for decades, but it has never applied consistently to the web. That may change once global companies start setting a new baseline. Even if no new laws appear, the precedent is clear. Accessibility is not a bonus. It is a requirement. Laws help, but they don’t write your code. Teams will need support. Tooling will need to catch up. Companies will need to invest in audits, training, and inclusive hiring. But the momentum is there. And for once, it isn’t being driven by blog posts or industry talks. It’s being driven by legislation with actual teeth. For years, accessibility experts have asked companies to take this seriously. Now they have to. Turns out the web gets fixed quicker when ignoring it brings in the lawyers.

0 views
Den Odell 3 months ago

AI Is Just the Latest Frontend Killer. Don’t Panic.

Apparently, frontend developers are about to be made obsolete. AI can scaffold a site from a prompt, restyle it mid-conversation, and write tests it will never have to maintain. It’s fast. It’s confident. And according to some, it means we’re done here. This all sounds very familiar. The first time I saw an AI coding assistant write a React component, I paused. It used the right hook. Destructured props neatly. Even remembered the . Well, I thought, there goes the frontend job market. But the more I used it, the more I tried to hand it real work, the more it missed the mark. It was fast, yes. But shallow. Confident, but clueless. It could write code, but not the right code. Not in the way I needed it. And that’s when it clicked: the risk isn’t that AI will replace frontend jobs. It’s that it will replace the ones that were already replaceable . AI coding assistants are great at scaffolding UIs, rewriting code, even generating decent boilerplate for common components. But they don’t know why one pattern is better than another. They don’t care about CLS or INP or how something feels when a user taps it on a laggy phone. They don’t push back when 300kB of JavaScript bloats the homepage . Frontend engineering isn’t just building. It’s choosing. Tuning. Diagnosing. Holding the line when product wants “just a quick popup” and you know it’ll tank performance. I’ve seen the posts. AI tools generating complete sites in a single session. Pixel-perfect designs from a few prompts. “Production-ready” apps without a line of hand-written code. And yes, it’s impressive. The scaffolding is faster than ever. The demos look clean. But when you try to scale them, test them, or make them fast, accessible, and reliable across real devices and real users? That’s where the job actually begins. And that’s not something I trust a code generator to own. I still write code, of course. But I also… These aren’t things I want to outsource. They’re the job. I do use AI. It helps me prototype faster, summarize unfamiliar APIs, and draft tests I’d rather not write by hand. Sometimes it even surprises me with a pattern I hadn’t considered. But I never copy anything I don’t understand. I don’t ship what I wouldn’t explain. I’ve done on-call . I’ve supported real users at real scale. And I can tell you, I wouldn’t want to be the one debugging production issues in code I didn’t fully understand, especially not at 2am. If AI wrote it, I need to own it before I ship it. The responsibility, the judgment, is still mine. I’ve been building for the web professionally for 25 years. That’s long enough to have watched entire tech stacks rise and fall. From table layouts to Flash to jQuery to SPAs to server-first rendering and back again. And I’ve seen the “death of frontend” declared more than once. When Dreamweaver promised you’d never need to write HTML again. When Flash and Silverlight tried to replace the browser. When JavaScript frameworks told us the DOM was obsolete. When no-code tools promised designers wouldn’t need developers. Now it’s AI’s turn. Each time, the pitch was the same: this new thing writes the code for you. But the complexity didn’t go away. It just shifted. And the need for people who understand users, performance, and systems never disappeared. So what’s different this time? Not much. Just the speed, and the hype. AI is better than the tools that came before it. No question. But the fundamentals of great frontend work haven’t changed: fast interactions, inclusive experiences, clear architecture, systems thinking. We debug the weird bugs. We balance performance with design. We build for everyone, not just the fast, the lucky, or the local. That’s what real frontend engineers do. That’s what I do. And I’m not planning to become obsolete anytime soon . UPDATE 21 Aug 2025 . An updated, extended version of this article can be found on Hacker Noon: https://hackernoon.com/ai-wants-to-kill-the-frontend-developer-it-wont-work Trace where the bloat comes from Fix interactivity delays no audit tool flags Catch the missing before it hits QA Explain to designers why we can't animate everything, everywhere, all at once

0 views
Den Odell 3 months ago

Building the Web in Islands, Not Mountains

Not every site needs to be a full-blown app. In fact, most don’t. What they need is to be fast, focused, and respectful of the user’s device. Put another way: if your ‘About Us’ page needs 300kB of JavaScript to render a sentence about your mission, it may be time to reconsider . We’ve leaned heavily into building everything as if it were an application: routing, state, hydration, and all. That approach works brilliantly for complex, interactive experiences. But for many sites, it leads to overengineered pages, unnecessary JavaScript, and slower interactions. There’s a better pattern, and it’s gaining momentum again. It’s called islands architecture , and it offers a way to ship less, do more, and give users speed where it counts. Single-page apps (SPAs) brought a wave of innovation to the frontend. They gave us smooth routing, shared state, and dynamic interactivity. For many use cases, they remain the right choice. But when every page becomes part of one large application, even simple, mostly static ones, we start to pay a price. That price often includes larger bundles, delayed interactivity, and more work for the browser than is truly needed. If your marketing page or blog post loads the same hydration logic and route configuration as your account dashboard, something is off. It creates work that doesn’t need to happen, especially on mobile. Islands architecture takes a more selective approach. It renders the majority of the page server-side, using static HTML whenever possible, and hydrates only the components that need to be interactive. Picture a page as a landmass. Most of it — layout, content, structure — is pre-rendered and delivered instantly. Then come the islands : self-contained interactive parts like a search box, a shopping cart, or a comment form. These hydrate independently and only when needed. Instead of treating every page like a fully hydrated application, you focus interactivity where it adds the most value. Before SPAs and JavaScript frameworks, developers often rendered pages server-side and used scripts sparingly to enhance behavior. You’d write HTML, sprinkle in jQuery plugins, and call it a day. In hindsight, this was a kind of early islands model. The challenge was maintainability. Everything felt stitched together. Today’s tools bring back the same mindset, but with component-based discipline and modern developer ergonomics. Frameworks like Astro are built with islands in mind. You can specify how and when a component should hydrate: This tells Astro to render the component on the server and hydrate it only once the page is idle. Other directives include , , and , letting you match hydration to user context. Other frameworks take similar or adjacent approaches: These are not opposing models. They are part of a broader shift toward delivering more HTML and less JavaScript when appropriate. And most importantly, it feels better. The page is usable immediately. You don’t wait for hydration to finish or for a loading spinner to disappear. Islands architecture shines when: It’s a great fit for blogs, marketing pages, documentation sites, and e-commerce product pages. Anywhere that’s mostly static but benefits from pockets of interactivity. For complex apps with deep state and interactive workflows, a hybrid model may make more sense. But even there, treating your UI as a set of islands can still lead to smarter hydration, clearer boundaries, and better performance. The trend is clear. Edge rendering, streaming, and component-level monitoring are all rising. Islands work well in this environment. They support: If your stack supports server rendering and hydration control, you are already most of the way there. Modern frameworks brought us power, flexibility, and developer joy. But they also nudged us toward treating every site like a full application. Islands architecture brings balance. It keeps the parts of modern development that work, such as components, server-side rendering, and interactivity, and refocuses them around speed, simplicity, and user needs. You don’t need to build a mountain for every page. Islands get users where they need to go. Without the altitude sickness . Qwik uses resumability , which avoids hydration entirely by serializing state for instant interactivity. Enhance.dev leans into web standards and progressive enhancement. Fresh (Deno) supports islands as a core rendering model. Even Next.js , with React Server Components and the directory, is giving developers more fine-grained control over what runs where. Less JavaScript up front means quicker interactivity. Fewer layout shifts make the experience more stable. Lower memory and CPU usage helps users on mid-range or older devices. Core Web Vitals like LCP, INP, and CLS often improve naturally. Your content is mostly static, with pockets of interactivity. You care about first load performance. Your audience includes mobile users or bandwidth-constrained regions. HTML streaming for faster time to first byte. Incremental rendering and delivery. Real user monitoring at the component level. Smarter delivery based on user context such as device, viewport, and connection speed.

0 views
Den Odell 4 months ago

Hacking Layout Before CSS Even Existed

Before , before , even before , we still had to lay out web pages. Not just basic scaffolding, full designs. Carefully crafted interfaces with precise alignment, overlapping layers, and brand-driven visuals. But in the early days of the web, HTML wasn’t built for layout. CSS was either brand-new or barely supported. Positioning was unreliable. Browser behavior was inconsistent. And yet, somehow, we made it work. So how did we lay out the web? With tables. Yup. Tables. Not the kind used for tabular data. These were layout tables, deeply nested, stretched and tweaked, often stuffed with invisible spacer GIFs to push elements into place. Text, links, and buttons were dropped into cells and floated among a scaffolding of invisible structure. If you were building websites in the late ’90s or early 2000s, this will sound familiar. If not, consider this a quick trip back to one of the more creatively chaotic eras of frontend development, and what it can still teach us today. HTML began as a way to mark up academic documents. Headings, paragraphs, links, lists, that was about it. There was no real concept of “layout” in the design sense. Early browsers had little support for positioning or styling beyond font tweaks and basic alignment. But developers still wanted structure. And clients, especially as the web grew more mainstream, wanted their brands to show up consistently. They expected full visual treatments: custom type, precise alignment, multi-column layouts, and logos in exactly the right place. Designs weren’t just documents, they were meant to look like something. Often like print. Often pixel-perfect. So we did what developers always do: we got creative. HTML tables gave us something no other element did at the time: control. You could create rows and columns. You could define cell widths and heights. You could nest tables inside tables to carve up the page into zones. That control was intoxicating. It wasn’t elegant. It definitely wasn’t semantic. But it worked. Spacer GIFs like the one above were a standard trick. You’d create a 1×1 pixel transparent image, then stretch it using width and height attributes to force the browser to reserve space. There were entire toolkits built to generate spacer-driven layouts automatically. If you wanted padding, you’d nest another table. For alignment, you’d add empty cells or tweak the attribute. And when that wasn’t enough, you’d resort to comment-tag hacks or browser-specific rendering quirks just to make things behave. At agencies like AKQA, where I worked at the time, the designs weren’t simple page frames. They were fully realized compositions, often with custom art direction, background textures, and layered effects. We’d receive static visuals, usually Photoshop files, and break them apart manually into dozens of individual image slices. Some slices were background textures. Some were visual foreground elements: shadows, corners, borders, custom typography before existed. Then we’d reassemble everything with HTML tables, mixing sliced images with live HTML, real text, buttons, form inputs, to recreate the original design as closely as browsers would allow. It was part engineering, part pixel-pushing, part dark art. It’s easy to laugh now, but back then layout tables gave us something CSS didn’t: predictability . CSS support was spotty. Browsers implemented it inconsistently. You could spend hours tweaking styles, only to have them break in IE5.5. Tables weren’t perfect, but they rendered the same almost everywhere. WYSIWYG tools like Dreamweaver leaned hard into the table model. You’d drag content into cells and it would spit out layers of nested HTML you weren’t really meant to touch. Was it bloated? Yes. Fragile? Absolutely. But it shipped. CSS1 arrived in 1996. CSS2 in 1998 brought , , and . But it took years for browsers to catch up, and even longer for developers to trust it. The table era didn’t really end until the mid-2000s, when modern browsers matured and CSS layout finally became viable. Even then, it took time for the idea of separation of concerns to take hold: structure in HTML, style in CSS, behavior in JavaScript. Now we have and . We can align elements without nesting. We can reorder content for accessibility. We can build responsive layouts without a single spacer GIF in sight. What used to take 100 lines of messy table markup now takes 10 lines of clean, declarative CSS. It’s better for developers, and for users, especially those using assistive tech that struggled to parse table-based scaffolding. A few lessons from the layout table era still hold true: Table-based layouts were a workaround. But they also reflect something constant about web development: we’re always adapting. Always hacking. Always building better experiences with the tools we have, until the next set of tools comes along. So next time you float a div or write a neat little grid template, give a small nod to the table layouts that walked so Flexbox could run. Cross-browser consistency matters. Even now, not everything renders the same. Test broadly. You’ll always work with constraints. Back then it was no CSS. Today it might be legacy code, team skills, or framework limitations. Creativity under constraint is part of the job. Understand the tools you’re misusing. Tables weren’t designed for layout, but we understood them deeply. That same mindset helps today when bending modern tools to fit the real world.

0 views
Den Odell 4 months ago

Want to Be a Better Frontend Engineer? Try a Week On-Call

You’re going to hate me for saying this, but I actually like being on-call. I know. I know. But hear me out. Obviously not the part where PagerDuty yanks you out of a dream with your heart pounding. But on-call taught me more about frontend quality than any bug tracker ever did. It was 2:43 AM. A customer couldn’t click through to checkout. Revenue was on the line. And the alert came to me. The root cause wasn’t in the frontend. A backend job had failed quietly, returning malformed data. But to the user, the result was simple: the button didn’t work. And when you’re on-call for the frontend, you’re the one who has to respond, no matter where the problem starts. I’ve always cared about quality. I’ve written tests, chased down edge cases, and treated polish as part of the craft. But on-call changes how you think about all of it. It’s not just about whether your code works. It’s about how it fails. It’s about how quickly it can be understood under pressure. It’s about whether your interface can recover from issues far outside your control. When something fails in the system, the user usually sees it in the frontend. If a service goes down, your component gets no data. If a token expires, the user gets stuck. If a third-party script blocks rendering, your buttons stop working. If checkout breaks, your app takes the blame. You may not control the systems upstream, but on-call teaches you that you still own the experience. On-call shifts your habits. You write clearer loading states. You handle empty, broken, or missing data. You stop assuming things will behave. You add useful logs. A lot of them. You recover from failure instead of hiding from it. You stop writing code that works in theory. You start writing code that holds up at 2 AM. You begin asking better questions: Because you might be. On-call brings accountability. You stop cutting corners you know might break later. You stop leaving vague TODOs for someone else. You stop letting “it works on my machine” be the final word. A single week of on-call teaches you what months of bug triage can’t. It shows you what real-world pressure feels like, and how it exposes every weak spot in your stack. And once you’ve lived through that, you start building differently. You start building better. What happens if this API returns nothing? What if the feature flag system is down? Will this UI leave the user stranded if it doesn’t render properly?

0 views