July 2026
Why I Replaced Next.js with Static HTML for Croatian Blog Archives
A Croatian developer explains why static HTML outperformed Next.js for blog archives, cutting JS bloat and improving mobile performance
I’ve spent the last decade building sites for Croatian clients, from small obrt shops in Zagreb to growing e-commerce brands in Split. For years, my default stack for any content-driven site was Next.js—it felt like the responsible choice. Then I rebuilt a modest blog archive page for a local history site, and something snapped. The page was serving 200 KB of JavaScript just to display a list of post titles and dates. For a Croatian audience where mobile data is still a real cost and rural internet can be spotty, that felt indefensible. I replaced Next.js with a single static HTML file, and the page went from a 4-second load to under 200 milliseconds. Here’s why I’m not going back.
The Real Cost of Over-Engineering a Blog Archive
What a Blog Archive Actually Needs
A blog archive page has one job: show a list of posts, sorted by date or category, so readers can find older content. It doesn’t need real-time updates, user authentication, or interactive charts. Yet most frameworks treat it like a full-blown application. Next.js, for all its strengths, ships a hydration payload that parses, re-renders, and attaches event listeners to every DOM element. On a simple archive with 50 links, that’s pure overhead.
I’ve seen Croatian news portals load a 2 MB JavaScript bundle just to render a table of article headlines. The user clicks a link, the page transitions with a client-side router, and the browser spends 500 milliseconds rehydrating the new route—for a page that could be a plain HTML file with inline CSS. The disconnect between what the user needs and what the framework provides is staggering.
The Data That Changed My Mind
I ran Lighthouse audits on ten Croatian blog archives built with Next.js. The median Time to Interactive was 3.8 seconds on a 3G connection. The same content, served as static HTML, hit 0.9 seconds. More importantly, the JavaScript bytes were cut by 95%. For a reader in a village near Rijeka with a limited mobile plan, that difference isn’t theoretical—it’s the difference between bouncing and reading.
One client’s archive had 200 posts. The Next.js build generated 200 static pages plus a client-side bundle for navigation. The total build output was 4.5 MB. When I rewrote it as a single HTML page with server-side includes for the list, the entire archive weighed 120 KB. The client’s hosting bill didn’t change, but their bounce rate dropped by 18% within two weeks.
The Croatian Context: Why Framework Bloat Hurts More Here
Mobile Data Costs and Rural Connectivity
Croatia has excellent mobile coverage in urban centers, but rural areas still rely on older 4G infrastructure. According to local telecom reports, average mobile data costs per GB are higher than in Western Europe. A 2 MB JavaScript bundle might cost a user a few cents—but more importantly, it eats into their monthly allowance. I’ve had clients tell me their readers in Dalmatia’s interior actively avoid image-heavy sites.
Static HTML doesn’t just load faster; it loads predictably. There’s no “spinner of death” while the framework hydrates. The content is visible the moment the first bytes arrive. For a blog archive, that’s the entire user experience.
The Maintenance Burden for Small Teams
Most Croatian blogs are run by one or two people—journalists, hobbyists, small businesses. They don’t have a dedicated devops person. Next.js requires a Node.js server, build pipelines, and periodic dependency updates. A static HTML archive can be edited with any text editor and uploaded via FTP. When a client needs to add a new post category, they don’t want to debug a broken getStaticProps call.
I once spent three hours updating a Next.js project because a minor version bump broke the next/link component. The archive page itself hadn’t changed in two years. That time could have been spent on actual content or SEO improvements. Static HTML sidesteps that entire class of problems.
How I Made the Switch (And What I Learned)
The Migration Path
I didn’t throw out Next.js entirely. For pages that genuinely need interactivity—like a contact form with client-side validation or a real-time search—I kept the framework. But the blog archive, category pages, and author bios became static HTML files generated by a simple Python script.
The script reads a JSON file with post metadata, loops through it, and writes an HTML file for each archive view (by year, by tag, by month). The output is a folder of .html files that I deploy to a plain web server. No build step, no hydration, no client-side routing. The browser just loads the page.
Handling Pagination Without JavaScript
Pagination was the trickiest part. With Next.js, I used client-side pagination with a state variable. In static HTML, I generate separate pages: archive-2023.html, archive-2024.html, and link them with standard <a> tags. Each page is a full HTML document, but since they share a common header and footer, I use server-side includes (SSI) to avoid duplicating code. Most Croatian hosting providers support SSI out of the box.
The result? Pagination works without any JavaScript. The browser preloads the next page when the user hovers over the link, and the click feels instant. No spinner, no layout shift.
A Concrete Example: The History Blog
I rebuilt an archive for a blog about Croatian maritime history. The original Next.js version had a client-side filter that let users sort by century. It was a nice feature, but analytics showed only 3% of visitors used it. The static version lists posts by century on separate pages—each one a 20 KB HTML file. The 3% of power users now click between five pages instead of using a dropdown, but the 97% get a page that loads in under a second.
The client’s feedback was telling: “I didn’t notice the difference until I tested it on my phone in the car.” That’s the goal—make the experience so fast that it becomes invisible.
When Static HTML Isn’t Enough
The Real-Time Exception
If your blog archive needs live updates—say, a news site that publishes breaking stories every minute—static HTML becomes impractical. Rebuilding 100 archive pages every time a new post goes live is wasteful. In that case, I’d still recommend a server-rendered framework, but with a lean approach: no client-side JavaScript for the archive itself, just server-generated HTML.
For most Croatian blogs, though, the update frequency is daily or weekly. A cron job that regenerates the static archive every hour is more than sufficient. I’ve set up such jobs on shared hosting for under €5 per month.
The SEO Trade-Off
Some developers argue that Next.js provides better SEO through server-side rendering. That’s true for dynamic content, but a static HTML file is the most SEO-friendly format possible. Search engines parse it instantly, there’s no JavaScript execution delay, and the content is fully visible in the source. Every blog archive I’ve migrated has seen either stable or improved rankings.
The one caveat is canonical URLs. With static HTML, you need to be careful about duplicate content if you generate the same list under multiple paths. I use a simple script that adds a <link rel="canonical"> tag to each page, pointing to the preferred version.
The Practical Takeaway
If you’re building a blog archive for a Croatian audience, start with static HTML. Don’t reach for a framework until you can articulate exactly what problem it solves that a plain file doesn’t. For 90% of archive pages, the answer is nothing. Your readers will thank you with lower bounce rates, and you’ll spend less time debugging dependencies.
I’m not abandoning Next.js entirely—it’s still my go-to for interactive dashboards and real-time applications. But for content that’s meant to be read, not clicked, I’ve learned that less is truly more. The next time you’re tempted to scaffold a new project with a heavy framework, ask yourself: does this page need to be an application? If not, write the HTML by hand. Your users—and your sanity—will benefit.