Next.js vs Remix for SaaS

Comparing Remix and Next.js for building SaaS applications, with key reasons to choose Remix for your next project.

NPM package downloads

Last week's download comparison for Next.js and Remix

Foundation

While Remix itself is newer than Next.js, the base of Remix, React Router, has been around for 10 years, making it one of the most battle-tested React libraries out there. For the past few years, the team behind both Remix and React Router have ensured nothing that makes its way into Remix without first being implemented in React Router. Recently, the team decided to merge both projects into one, React Router v7. All of this is to say that Remix is built on a solid foundation that has been around for a long time.

Low barrier to entry

Remix has very little magic involved and is built on top of web standards. This means that you can use the same tools and techniques you're already familiar with to build your app without having to learn a ton of new concepts.

Remix uses Vite for bundling, which is the gold standard for modern JS bundling. It also uses the native Web Fetch API for data fetching, which is a web standard that is built into the browser and Node runtimes. It also uses native HTTP headers for caching, giving you full control over how your data is cached without having to learn a new caching system.

Next.js in comparison, still uses the somewhat dated Webpack bundler, with a new Webpack-compatible bundler (Turbopack) still in development. It also patches the native Web Fetch API to support its internal caching system, which itself can cause major headaches when trying to debug issues with data fetching.

Focus of the framework

Remix is built with a focus on building web applications, not just websites. This means that it has built-in support for crucial SaaS functionality like form handling, data fetching, mutations, and automatic revalidations.

Compare the code below for handling a simple form submission in Remix vs Next.js

// Remix export default function ContactForm() { return ( <Form method="post"> <input type="text" name="name" /> <input type="email" name="email" /> <button type="submit">Submit</button> </Form> ) } export async function action({ request }) { const formData = await request.formData() const name = formData.get('name') const email = formData.get('email') // Process form data server-side return json({ success: true }) }
// Next.js import { useState } from 'react' export default function ContactForm() { const [formData, setFormData] = useState({ name: '', email: '' }) const handleSubmit = async (e) => { e.preventDefault() const response = await fetch('/api/contact', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formData), }) const data = await response.json() // Handle response } return ( <form onSubmit={handleSubmit}> <input type="text" value={formData.name} onChange={(e) => setFormData({ ...formData, name: e.target.value })} /> <input type="email" value={formData.email} onChange={(e) => setFormData({ ...formData, email: e.target.value })} /> <button type="submit">Submit</button> </form> ) } // pages/api/contact.js export default function handler(req, res) { if (req.method === 'POST') { // Process form data res.status(200).json({ success: true }) } else { res.status(405).end() } }

Now imagine you have tens of hundreds of forms like this throughout your app and you can see the benefits of Remix's approach.

Caching

As well, while Next.js and Remix both share a base of SSR-focused development, Next.js also supports static site generation (SSG) and incremental static regeneration (ISR). Supporting SSR, SSG and ISR out of the box means that Next.js has to make trade-offs in terms of how it handles data fetching and caching, resulting in lots of complexity and magic under the hood. In contrast, Remix is focused on SSR and client-side rendering (CSR) and has a much simpler and more predictable data fetching and caching model.

Even if you do wish to do SSG, the next version of Remix/React Router will support it out of box using a few lines of code in your Vite config. No need to learn a new caching system or deal with the complexities of ISR.

Vendor lock-in

Remix is ultimately just a runtime around React Router so can be deployed in any combination of ways. It can be an Express server, in a Docker container, you could use Node, Deno or Bun and it can be deployed to basically serverless or server-ful environment. Next.js, in contrast, is famously difficult to self-host outside of Vercel, so much so that there's a dedicated solution, OpenNext, to fill in the gaps. Not being in control of your deployed code can be a huge burden when starting off a new project so Remix's flexibility is a huge advantage.

Risk comparison

Remix is owned by Shopify, a public company which IPO'd almost 10 years ago. The incentive for Shopify to maintain and support Remix is clear, as it is a key part of their own platform. Next.js, on the other hand, is owned and maintained by Vercel, a private company that has raised over $100 million in venture capital. While Vercel has a strong incentive to maintain and support Next.js, the risk of the company going under or being acquired is higher than with Shopify.

Launchway is a starter kit for Remix that helps you get started with building your SaaS app. It comes out of the box with authentication, payments, database connection, email handling and more so you can focus on building your app, not the boilerplate code. If you're interested, check out one of the demo apps.