React Native Finally Dropped the Asterisk
Nejc Furh/

React Native Finally Dropped the Asterisk

React Native has been "almost as fast as native" for so long that the qualifier became part of the pitch. In 2026 you can mostly drop the qualifier, and the reason is a multi-year rewrite that finally shipped as the default: the New Architecture. The old React Native worked by sending messages across a bridge between JavaScript and the native side. Every gesture, every layout update, every list scroll was serialized into JSON, passed across, and deserialized on the other end. It was clever and it was also the source of most of the jank anyone ever complained about. The bridge was a bottleneck you could feel. The New Architecture removes it. JSI lets JavaScript hold direct references to native objects and call them synchronously. Fabric is a new rendering system that can do layout and updates without the round-trip. TurboModules load native modules lazily instead of all at once at startup. None of these are new ideas as of 2026 — what is new is that they are on by default. The fast path is now the path you get without opting in. The practical effect is that the categories of app that used to be "you should probably go native for this" have shrunk. Heavy lists, complex gesture-driven interfaces, animations that need to track a finger at sixty or a hundred and twenty frames a second — these are now reasonable in React Native rather than heroic. The performance argument for going fully native has not vanished, but it applies to a much narrower slice of apps than it did three years ago. The other shift is on-device AI. Running a model on the phone instead of a server is suddenly normal: it is private, it works offline, and it has no per-request cost. React Native bridges into the platform's machine learning runtimes, so a translation feature, a smart camera, or an on-device assistant can live inside the same JavaScript codebase as the rest of the app. A majority of mobile developers now ship some AI feature, and increasingly that inference happens locally. Underneath all of it is the same unglamorous advantage React Native always had: there are vastly more JavaScript developers than there are specialists in any single native platform. One codebase, one language, two app stores, and now performance that no longer comes with an asterisk. For most teams in 2026, that math is hard to argue with.

Writing & Notes

BLOG

The Archive

Latest posts

React Native Finally Dropped the Asterisk
Nejc Furh/

React Native Finally Dropped the Asterisk

React Native has been "almost as fast as native" for so long that the qualifier became part of the pitch. In 2026 you can mostly drop the qualifier, and the reason is a multi-year rewrite that finally shipped as the default: the New Architecture. The old React Native worked by sending messages across a bridge between JavaScript and the native side. Every gesture, every layout update, every list scroll was serialized into JSON, passed across, and deserialized on the other end. It was clever and it was also the source of most of the jank anyone ever complained about. The bridge was a bottleneck you could feel. The New Architecture removes it. JSI lets JavaScript hold direct references to native objects and call them synchronously. Fabric is a new rendering system that can do layout and updates without the round-trip. TurboModules load native modules lazily instead of all at once at startup. None of these are new ideas as of 2026 — what is new is that they are on by default. The fast path is now the path you get without opting in. The practical effect is that the categories of app that used to be "you should probably go native for this" have shrunk. Heavy lists, complex gesture-driven interfaces, animations that need to track a finger at sixty or a hundred and twenty frames a second — these are now reasonable in React Native rather than heroic. The performance argument for going fully native has not vanished, but it applies to a much narrower slice of apps than it did three years ago. The other shift is on-device AI. Running a model on the phone instead of a server is suddenly normal: it is private, it works offline, and it has no per-request cost. React Native bridges into the platform's machine learning runtimes, so a translation feature, a smart camera, or an on-device assistant can live inside the same JavaScript codebase as the rest of the app. A majority of mobile developers now ship some AI feature, and increasingly that inference happens locally. Underneath all of it is the same unglamorous advantage React Native always had: there are vastly more JavaScript developers than there are specialists in any single native platform. One codebase, one language, two app stores, and now performance that no longer comes with an asterisk. For most teams in 2026, that math is hard to argue with.

We Stopped Chatting With AI and Started Handing It Work
Nejc Furh/

We Stopped Chatting With AI and Started Handing It Work

The most interesting thing about AI in 2026 is not that the models got smarter. It is that we stopped talking to them and started handing them work. For the first few years, the dominant interface was chat. You typed a question, you got an answer, you copied something useful out of it, and you did the actual work yourself. The model was a very well-read colleague who could only ever talk. That era is ending. The headline capability of every major model release this year has been agentic: the ability to take a goal, break it into steps, use tools, run commands, read the results, and keep going until the job is done. The numbers around coding agents make the shift concrete. Anthropic's Claude Code, an agentic coding tool, reportedly reached billions in annual revenue within a year of launch. The benchmarks that people actually care about now are not trivia quizzes — they are things like Terminal-Bench, which measures whether a model can sit in a real terminal and finish real tasks. The competition at the top is between agents, not chatbots. This changes what it feels like to build software. Instead of asking "how do I write this function," you increasingly describe an outcome — "add pagination to this endpoint and update the tests" — and review a finished change. The unit of work moves up a level. You spend less time typing and more time specifying, reviewing, and deciding. That is a different skill, and not everyone has noticed they need to develop it. It also raises the stakes on a few unglamorous things. An agent that can run commands can run the wrong command. An agent with access to your tools has your permissions. Reviewing a diff you did not write, written by something that is confident either way, is a discipline. The teams getting value out of agents are the ones who built guardrails — sandboxes, limited permissions, mandatory review — not the ones who turned everything loose and hoped. The honest summary is that agents are real and useful and still occasionally wrong in ways that look right. The productivity gains are not hype; a lot of routine engineering work genuinely compresses. But "the agent did it" is not a place to hide. Someone still has to own the outcome, and in 2026 that someone is still you. The job did not disappear. It moved up the stack.

The Web Went Back to the Server, and It Was the Right Call
Nejc Furh/

The Web Went Back to the Server, and It Was the Right Call

For a decade the frontend industry kept moving work toward the browser. We shipped bigger bundles, hydrated everything, and asked the user's phone to reassemble an app that the server had already rendered once and then thrown away. It worked, but it never felt great — and in 2026 the pendulum has clearly swung back toward the server. The shift has a name now: server-first. The default in modern meta-frameworks is to render UI on the server and send only the JavaScript that a given piece of the page actually needs to be interactive. React Server Components are the clearest example. A component that just reads data and prints it never ships to the client at all. The bytes you save are not micro-optimizations; they are entire libraries that simply never reach the browser. What makes this more than a fad is that it lines up with how the web is actually used. Most pages are mostly static. A product page has one "add to cart" button surrounded by text and images that never change after render. The old model paid the hydration tax on all of it. The new model pays only for the button. On the client side, the other half of the story is fine-grained reactivity. Signals — in SolidJS, in Svelte 5's runes, in Angular — track dependencies at the level of individual expressions instead of whole components. When a value changes, only the exact DOM node that reads it updates. No virtual DOM diff, no re-running a component function, no guessing. After years of "re-render the world and let the diff sort it out," tracking dependencies precisely feels almost obvious in hindsight. There is a cost to all of this, and it is worth naming. Server-first blurs the line between server and client in ways that are genuinely confusing at first. "Can I use this hook here?" becomes a real question with a non-obvious answer. The mental model of where code runs is now something you have to hold in your head deliberately, where before you could pretend everything ran in the browser. But the trade is a good one. We are moving boring, repetitive work — fetching, templating, formatting — back to a place that is fast, controlled, and close to the data. And we are reserving the browser for what it is uniquely good at: responding to the person in front of it. After years of asking phones to do the server's job, that feels like the right correction.

Why Next.js Still Feels Like the Right Kind of Opinionated
ChatGPT/

Why Next.js Still Feels Like the Right Kind of Opinionated

There is a certain kind of framework fatigue that hits after building enough web apps. You start by wanting flexibility, then spend months wiring together routing, rendering, caching, image handling, API boundaries, metadata, deployment settings, and performance fixes that you were supposed to “have full control over.” Eventually you realize that full control often means full responsibility for a pile of boring infrastructure decisions. That is part of why Next.js keeps winning teams over. Next.js is not popular because it is magical. It is popular because it removes a long list of decisions that most teams do not actually want to make from scratch. It gives you a default structure for React applications that covers the ugly middle ground between a simple frontend and a real production product. That middle ground is where most apps live, and it is exactly where weak tooling becomes expensive. The strongest argument for Next.js is not speed. It is coherence. A modern app usually needs server rendering in some places, static generation in others, client interactivity on selected screens, image optimization, predictable routing, API endpoints, metadata control, and deployment that does not become a separate engineering project. Next.js gives you one mental model for all of that. It is not always elegant, but it is practical. That matters more. The App Router pushed this even further. Some developers disliked it because it forced a shift in how they think about React. Fair criticism. But it also made one thing clearer: not everything should be a client component. Shipping less JavaScript is still one of the few performance wins that reliably matters. Next.js now gives developers a more explicit boundary between what belongs on the server and what actually needs to run in the browser. That is a good constraint. Of course, there is a price. Next.js can feel heavy-handed. The framework evolves quickly, some APIs age out faster than teams would like, and the line between React behavior and Next behavior is not always obvious. Debugging can also get messy when rendering strategy, caching, and data fetching interact in ways that are technically correct but operationally annoying. Still, those are the tradeoffs of a framework that is trying to solve real production problems instead of staying ideologically pure. The truth is simple: most teams do not need a blank canvas. They need a framework that helps them ship. They need conventions that reduce arguments. They need tooling that works well enough with TypeScript, deployment pipelines, SEO, content, dashboards, and marketing pages in the same repo. Next.js is good at that. Not perfect. Good. That is why it remains relevant. Not because it is the cleanest possible abstraction. Not because every developer loves every new release. But because it understands what web teams actually deal with: messy products, mixed rendering needs, shifting priorities, and constant pressure to deliver faster without letting the stack fall apart. Next.js is not exciting in the way a brand-new framework is exciting. It is valuable in the way a proven system is valuable. It absorbs complexity so your team can spend more time on product logic and less time rebuilding table stakes. That is not hype. That is utility. And utility tends to win.

How much do you really know about media queries?
Daniel Schwarz/

How much do you really know about media queries?

Earlier this year, I realized that I knew very little about possibly most of the media queries. Maybe that’s not surprising — since I never hear about them. Beyond the classics like @media(min-width: 400px) and the user-preference media queries such as @media (prefers-reduced-motion: reduce), and maaaybe orientation, I can’t say that I was using media queries a whole lot. Especially since flexbox, grid layout, and calc() became fairly normalized, in addition to newer sizing values such as min-content, max-content, fit-content, and more recently, stretch. But there are so many descriptors! Most of these I’ve never used: any-hover any-pointer aspect-ratio color color-gamut color-index display-mode dynamic-range environment-blending forced-colors grid height horizontal-viewport-segments hover inverted-colors monochrome nav-controls orientation overflow-block overflow-inline pointer prefers-color-scheme prefers-contrast prefers-reduced-data prefers-reduced-motion prefers-reduced-transparency resolution scan scripting update vertical-viewport-segments video-color-gamut video-dynamic-range width It’s not that I thought media queries were only for responsive design, but out of sight, out of mind, right? Nobody talks about them. Granted, some of them have few use-cases, but after being more mindful of them for a few months, I’ve come to the conclusion that many of them definitely deserve more attention. Plus, there are more ways to write media queries now. This includes an @custom-media at-rule for saving media queries as custom properties, which is super cool. Let’s dig in. hover/pointer/any-hover/any-pointer Modern devices can be used in many different ways. For example, it’s not uncommon to hook a mouse up to a tablet, which is why we shouldn’t think of tablets as touchscreen devices anymore. In fact, it’s now unwise to use media queries to query for what specific device they “are”, which is why the media types tty, tv, projection, handheld, braille, embossed, aural, and speech were deprecated (all, print, and screen are the only types now, but all of them will likely be deprecated eventually). These days it’s more prudent to query the device’s capabilities and how the user has set it up, and that’s where the hover, pointer, any-hover, and any-pointer media query descriptors come into it. At first glance, hover and pointer sound like the same thing, and while you could use them interchangeably for a high-level use-case.

A Basic Introduction to Next.js
Nejc Furh/

A Basic Introduction to Next.js

Next.js is a React framework for building modern web applications that are fast, scalable, and production-ready. It’s widely used because it adds practical features on top of React—like routing, server rendering, and performance optimizations—without forcing you to assemble everything yourself. Next.js creates routes based on your project structure. Instead of manually wiring a router, you place pages (or route segments) in specific folders and Next.js handles the rest. Next.js supports multiple rendering strategies: Static Site Generation (SSG): pages are built ahead of time (fast, cacheable). Server-Side Rendering (SSR): pages are rendered on demand per request. Incremental Static Regeneration (ISR): static pages can be updated in the background on a schedule. This flexibility is useful because not every page in an app needs the same approach. Next.js lets you run backend logic alongside your frontend. Depending on your setup, you can use API routes or server functions to handle tasks like form submissions, authentication callbacks, or talking to a database—without maintaining a separate server. Next.js includes optimizations that typically require manual work: Automatic code splitting Image optimization Font optimization Bundling and caching improvements This results in faster load times and better Core Web Vitals with less effort. Modern Next.js projects often use the App Router (app/ directory). It introduces: Server Components by default (rendered on the server) Client Components when you need browser interactivity ("use client") Nested layouts and route segments Built-in loading and error handling patterns In practice, it helps you keep heavy work on the server while still using React for interactive UI where needed. A simple Next.js app often looks like this: app/ — pages, layouts, and routes components/ — reusable UI components lib/ — shared helpers (fetching, auth, db) public/ — static files (images, icons) This structure scales well as your app grows.