Live
Black Hat USADark ReadingBlack Hat AsiaAI BusinessCrack ML Interviews with Confidence: ML Model Development (20 Q&A)Towards AICoreWeave Stock Analysis: Buy or Sell This Nvidia-Backed AI Stock? - The Motley FoolGNews AI NVIDIAIntel Arc B70 Benchmarks/Comparison to Nvidia RTX 4070 SuperReddit r/LocalLLaMAI Gave Claude Access to My Desktop Outlook Without Touching the Microsoft APITowards AIBanning All Anthropic EmployeesHacker NewsMicrosoft is automatically updating Windows 11 24H2 to 25H2 using machine learning - TweakTownGoogle News: Machine Learning80 Years to an Overnight Success: The Real History of Artificial Intelligence - Futurist SpeakerGoogle News: AIGoogle’s Gemma 4 Tied Qwen 3.5 on Benchmarks. Then Won on One Word: Apache.Towards AIWhat next for the struggling rural mothers in China who helped to build AI?SCMP Tech (Asia AI)Apple reportedly signed a 3rd-party driver, by Tiny Corp, for AMD or Nvidia eGPUs for Apple Silicon Macs; it s meant for AI research, not accelerating graphics (AppleInsider)TechmemeBest Resume Builders in 2026: I Applied to 50 Jobs to Test TheseDEV CommunityTruth Technology and the Architecture of Digital TrustDEV CommunityBlack Hat USADark ReadingBlack Hat AsiaAI BusinessCrack ML Interviews with Confidence: ML Model Development (20 Q&A)Towards AICoreWeave Stock Analysis: Buy or Sell This Nvidia-Backed AI Stock? - The Motley FoolGNews AI NVIDIAIntel Arc B70 Benchmarks/Comparison to Nvidia RTX 4070 SuperReddit r/LocalLLaMAI Gave Claude Access to My Desktop Outlook Without Touching the Microsoft APITowards AIBanning All Anthropic EmployeesHacker NewsMicrosoft is automatically updating Windows 11 24H2 to 25H2 using machine learning - TweakTownGoogle News: Machine Learning80 Years to an Overnight Success: The Real History of Artificial Intelligence - Futurist SpeakerGoogle News: AIGoogle’s Gemma 4 Tied Qwen 3.5 on Benchmarks. Then Won on One Word: Apache.Towards AIWhat next for the struggling rural mothers in China who helped to build AI?SCMP Tech (Asia AI)Apple reportedly signed a 3rd-party driver, by Tiny Corp, for AMD or Nvidia eGPUs for Apple Silicon Macs; it s meant for AI research, not accelerating graphics (AppleInsider)TechmemeBest Resume Builders in 2026: I Applied to 50 Jobs to Test TheseDEV CommunityTruth Technology and the Architecture of Digital TrustDEV Community
AI NEWS HUBbyEIGENVECTOREigenvector

From Next.js to Pareto: What Changes and What Stays the Same

DEV Communityby reactuse.comApril 3, 20266 min read3 views
Source Quiz

You know Next.js. You know file-based routing, layouts, loaders, SSR. You probably also know the pain: server components vs client components, the "use client" dance, mysterious hydration errors, and a 233 KB client bundle before you write a single line of app code. Pareto gives you the same SSR patterns — but without the complexity. Standard React components, Vite instead of Webpack/Turbopack, and a 62 KB client bundle. This post walks through exactly what changes when you move from Next.js to Pareto, and what stays familiar. The mental model shift Next.js (App Router): Every component is a server component by default. Want useState ? Add "use client" . Data fetching happens via async server components or route-level generateMetadata . You're constantly thinking about the server/client bo

You know Next.js. You know file-based routing, layouts, loaders, SSR. You probably also know the pain: server components vs client components, the "use client" dance, mysterious hydration errors, and a 233 KB client bundle before you write a single line of app code.

Pareto gives you the same SSR patterns — but without the complexity. Standard React components, Vite instead of Webpack/Turbopack, and a 62 KB client bundle. This post walks through exactly what changes when you move from Next.js to Pareto, and what stays familiar.

The mental model shift

Next.js (App Router): Every component is a server component by default. Want useState? Add "use client". Data fetching happens via async server components or route-level generateMetadata. You're constantly thinking about the server/client boundary.

Pareto: Every component is a regular React component that runs on both server and client. Data fetching happens in loader.ts files — a pattern borrowed from Remix. There's no "use client" directive because there's no server component / client component split.

Enter fullscreen mode

Exit fullscreen mode

Routing: almost identical

If you know Next.js App Router conventions, Pareto's routing is immediately familiar:

Next.js Pareto Purpose

page.tsx page.tsx Route component

layout.tsx layout.tsx Wrapping layout

loader.ts Server-side data

loading.tsx Suspense + ``

Loading states

error.tsx ParetoErrorBoundary Error handling

not-found.tsx not-found.tsx 404 page

route.ts route.ts API endpoint

head.tsx / generateMetadata

head.tsx Meta tags

The biggest difference: Pareto uses a dedicated loader.ts file for data fetching instead of making the page component async.

Data fetching: loaders replace async components

Next.js (App Router):

Enter fullscreen mode

Exit fullscreen mode

Pareto:

export function loader(ctx: LoaderContext) { return { stats: db.getStats() } }

// app/dashboard/page.tsx import { useLoaderData } from '@paretojs/core'

export default function Dashboard() { const { stats } = useLoaderData<{ stats: { total: number } }>() return {stats.total} users }`

Enter fullscreen mode

Exit fullscreen mode

Two files instead of one, but the separation is intentional: data fetching is explicit, testable, and never mixed with rendering logic. The component is standard React — no async, no await, no server-only constraints.

Streaming: defer() instead of Suspense gymnastics

Next.js: Streaming requires splitting your page into server and client components, coordinating loading.tsx boundaries, and understanding which components block the initial render.

Pareto: Call defer() in your loader. Wrap slow data in . Done.

export async function loader() { const userCount = await getUserCount() // resolve fast data first

return defer({ userCount, // resolved — sent immediately activityFeed: getActivityFeed(), // slow — streamed later analytics: getAnalytics(), // slower — streamed even later }) }

// app/dashboard/page.tsx import { useLoaderData, Await } from '@paretojs/core'

export default function Dashboard() { const { userCount, activityFeed, analytics } = useLoaderData()

return (

{userCount} users

}> {(feed) => }

}> {(data) => }

) }`

Enter fullscreen mode

Exit fullscreen mode

Each creates its own Suspense boundary. Fast data renders immediately. Slow data streams in progressively. Same behavior on initial SSR load and client-side navigation (via NDJSON streaming in Pareto 4.0).

Head management: React components, not config objects

Next.js:

Enter fullscreen mode

Exit fullscreen mode

Pareto:

) }`

Enter fullscreen mode

Exit fullscreen mode

It's a React component. You can use conditional logic, compose from shared components, or render anything valid in . Head components merge from root layout to page — the deepest route wins for duplicate tags.

State management: built-in, not bolted on

Next.js has no opinion on state management. You bring your own Redux, Zustand, Jotai, etc., and figure out SSR hydration yourself.

Pareto ships defineStore() with Immer:

import { defineStore } from '@paretojs/core/store'

const { useStore, getState, setState } = defineStore((set) => ({ items: [] as CartItem[], total: 0, addItem: (item: CartItem) => set((d) => { d.items.push(item) d.total += item.price }), }))`

Enter fullscreen mode

Exit fullscreen mode

SSR hydration is automatic. State defined on the server is serialized and restored on the client without any manual dehydrate / rehydrate boilerplate.

Configuration: one file

Next.js: next.config.js for framework config + separate Webpack/Turbopack customization + potential middleware.ts + environment variable conventions.

Pareto: One pareto.config.ts:

import type { ParetoConfig } from '@paretojs/core'

const config: ParetoConfig = { configureVite(config) { // Standard Vite config — your plugins just work return config }, configureServer(app) { // Standard Express app — add any middleware app.use(cors()) }, }

export default config`

Enter fullscreen mode

Exit fullscreen mode

No framework magic. It's Vite and Express under the hood, both fully accessible.

The performance difference

We run automated benchmarks in CI comparing Pareto against Next.js on identical hardware:

  • Data loading throughput: Pareto 2,733 req/s vs Next.js 293 req/s (9.3x)

  • Streaming SSR capacity: Pareto 2,022 req/s vs Next.js 310 req/s (6.5x)

  • Client JS bundle: 62 KB vs 233 KB (73% smaller)

In infrastructure terms: a page serving 2,000 req/s needs 1 Pareto server vs 6 Next.js instances. Full benchmark details: paretojs.tech/blog/benchmarks

What you give up

Transparency matters. Here's what Pareto doesn't have:

  • Server components — No RSC, no "use client". This is by design: the loader pattern is simpler and covers 95% of use cases.

  • Image optimization — No component with automatic resizing. Use standard with a CDN.

  • ISR / Static generation — Pareto is SSR-only. No generateStaticParams(), no build-time rendering. If you need static pages, pair with a static site generator.

  • Middleware — No edge middleware concept. Use Express middleware in configureServer() instead.

  • Vercel integration — No one-click deploy. You deploy a standard Node.js server.

  • Ecosystem size — Smaller community, fewer examples. You're early.

If you're building a content-heavy marketing site with ISR, Next.js is still the right call. If you're building a data-driven app where performance and simplicity matter, Pareto is worth the switch.

Migration checklist

  • npx create-pareto@latest my-app — scaffold a new project

  • Move your routes from app/ — file structure is nearly identical

  • Extract async server components into loader.ts + standard component

  • Replace "use client" directives — they're not needed, just delete them

  • Move generateMetadata to head.tsx components

  • Replace loading.tsx with defer() + for streaming

  • Replace next/link with Link from @paretojs/core

  • Move Webpack config to configureVite() in pareto.config.ts

  • Deploy as a standard Node.js server

Enter fullscreen mode

Exit fullscreen mode

Pareto is a lightweight, streaming-first React SSR framework built on Vite. Documentation

Was this article helpful?

Sign in to highlight and annotate this article

AI
Ask AI about this article
Powered by Eigenvector · full article context loaded
Ready

Conversation starters

Ask anything about this article…

Daily AI Digest

Get the top 5 AI stories delivered to your inbox every morning.

Knowledge Map

Knowledge Map
TopicsEntitiesSource
From Next.j…modelbenchmarkintegrationmarketopinioncomponentDEV Communi…

Connected Articles — Knowledge Graph

This article is connected to other articles through shared AI topics and tags.

Building knowledge graph…

Discussion

Sign in to join the discussion

No comments yet — be the first to share your thoughts!