Blog.dev

A personal dev blog by Nejc Furh — software engineer building web apps with React, Next.js, Node.js, and TypeScript. Writing about code, projects, and lessons learned along the way.

Latest posts

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.