Next.js: The Love-Hate Relationship
I've shipped six Next.js apps to production. Two were complete disasters, three were okay, and one actually worked well. Here's what nobody tells you:
Next.js 15 has two completely different APIs depending on which router you use. Pages Router works but everyone says it's "legacy." App Router is the future but breaks constantly. Last year I spent two weeks migrating our auth flow to App Router only to hit hydration issues that made our login page completely unusable on mobile Safari. Turns out hydration mismatches with Safari are a known problem that nobody warns you about.
Real talk on bundle sizes: A basic Next.js app with a form and a few components ships like 180-200kb of JavaScript depending on what you import. Add any authentication library and you're looking at 250kb+ easy. Our e-commerce site struggled with 3G users because the JavaScript bundle was larger than some images.
The Vercel trap: Next.js deploys to Vercel in 30 seconds. Deploying anywhere else is a nightmare. Self-hosting requires understanding Node.js clustering, reverse proxies, and why your app randomly crashes with ENOMEM
errors. Check out the deployment guides and you'll see why our Vercel bill was getting stupid expensive - like $700-800 a month - so we moved to a cheap VPS for maybe $50 that required three days of DevOps hell.
Remix: Actually Enjoyable Web Development
Spent eight months in 2024 building a SaaS with Remix and it was the most fun I've had with React in years. Forms just work without client-side JavaScript. No hydration errors. No "useEffect hell" for data fetching.
The big brain shift: Remix makes you think like it's 2005 again - forms submit to the server, pages load with data already there. React developers hate this at first because their SPA brain is so broken. Read about web standards and progressive enhancement. But after a week, you realize how much simpler everything becomes.
Real production story: Our payment processing never failed once in eight months. Compare that to our Next.js app where Stripe webhooks randomly failed because of SSR/client state mismatches. Remix's form handling with progressive enhancement just works. Check their data patterns for more details.
The React Router 7 evolution: Yes, it broke our imports and took a weekend to fix. But now we have Shopify's backing and the framework is stronger than ever. The migration was worth the pain.
SvelteKit: The Performance Monster
Built a content site with SvelteKit that loads in like 400ms on 3G (faster if caching cooperates). The entire JavaScript bundle is around 28kb. Compare that to our Next.js marketing site that ships over 200kb for a landing page with three fucking buttons.
The ecosystem reality: Need a date picker? Build it yourself. Want authentication? Roll your own or adapt a React library. I spent two days building a dropdown component that would've taken 5 minutes with React. But the result was 2kb instead of 50kb.
Hiring nightmare: Posted a Svelte job on three platforms. Got two qualified applicants in six weeks. Posted a React job and got 47 applicants in two days. Had to train our React team on Svelte, which took about a month to get productive.
Adapter confusion: SvelteKit adapters are great in theory but the wrong choice breaks deployment silently. Spent four hours debugging why our Node.js adapter wasn't generating server routes, turns out we needed the auto adapter for our hosting setup.
Performance Numbers That Actually Matter
Tested all three frameworks on our staging environment with real user data:
Mobile performance on budget Android (4GB RAM, slow CPU):
- Next.js: Takes like 3-4 seconds to actually work, sometimes longer if the phone is being shitty
- Remix: Around 2 seconds to interactive, content shows up right away since it's server-rendered
- SvelteKit: Usually interactive in just over a second, feels almost instant
Developer build times (medium-sized app with auth + dashboard on my M1 Mac):
- Next.js: Like 45-50 seconds cold start, sometimes up to a minute if it's feeling slow, hot reload takes maybe 8-12 seconds
- Remix: Around 12-15 seconds cold start, hot reload is usually 2-3 seconds
- SvelteKit: Maybe 8-10 seconds cold start, hot reload is basically instant
The Shit Nobody Talks About
OK, rant over about the marketing bullshit. Here's the technical reality of what actually breaks in production:
Next.js gotchas that killed our weekends:
- Memory leaks in development mode that crash Node.js after 200 requests
getServerSideProps
randomly returning empty objects in production (still happens in 15.0.3)- Image optimization that works locally but fails on Docker with
Error: Cannot find module 'sharp'
- App Router edge cases that break without warning, especially nested layouts
Remix pain points:
- TypeScript errors in loader functions that only show up at runtime
- Nested routes are powerful but confusing for new developers
- No built-in caching strategy - you're on your own
- Error boundaries can be tricky to debug
SvelteKit sharp edges:
- Adapter documentation assumes you understand deployment internals
- Breaking changes between major versions require rewriting components
- Some npm packages just don't work and there's no workaround
- SSR hydration mismatches can be cryptic to debug
The honest truth: they all have problems. Pick the problems you can live with.