React SPA vs Next.js: How I Stopped Feeling Guilty About My Tech Choices
I kept feeling guilty for not using Next.js.
Every job posting demanded it. The React documentation pushed me toward it. Even my colleagues gave me that look when I suggested Vite for our internal dashboard.
But here’s the thing: our dashboard didn’t need server-side rendering. It didn’t need SEO. It didn’t need edge functions.
I was about to over-engineer a simple CRUD app because of ecosystem pressure.
The Problem: Ecosystem Gaslighting
A recent Reddit thread captured exactly what I was feeling. The original poster said:
“Can we normalize just building a standard React SPA with Vite again without feeling guilty that we aren’t using Next.js?”
This resonated with thousands of developers. The frontend ecosystem has created unnecessary guilt around technology choices.
Here’s what’s happening:
Job Market Reality Your Project Reality------------------- --------------------"Must know Next.js" vs "Internal dashboard""SSR experience" vs "Behind authentication""Edge functions" vs "Simple CRUD operations"The mismatch is real. But the pressure to conform is stronger.
When I Chose the Wrong Tool
I’ll admit it. I once started a project with Next.js “just in case.”
The project was an admin panel for managing user permissions. Three weeks in, I realized:
- I was fighting client/server component boundaries constantly
- I had to extract components to “use client” files repeatedly
- The caching strategy was adding complexity I didn’t need
- Deployments required server infrastructure instead of simple static hosting
The worst part? None of my users were Googling “admin panel for user permissions.” SEO was completely irrelevant.
I had added complexity for features I would never use.
The Decision Framework
After making this mistake, I created a simple decision tree:
Does your app need SEO? | +------------+------------+ | | YES NO | | Public content? Auth required? | | +--------+--------+ +--------+--------+ | | | | E-commerce Marketing YES NO storefront site | | | | Use SPA Use SPA Use Next.js Use Next.js | | +--------+--------+ | Performance critical? | +-----+-----+ | | YES NO | | Consider Consider Next.js both fineLet me break this down with real examples.
When to Use React SPA with Vite
Best for these scenarios:
| Scenario | Why SPA Works |
|---|---|
| Internal dashboards | No SEO needed, behind auth |
| Admin panels | CRUD operations, authenticated users |
| SaaS applications | Users log in, content is private |
| Personal projects | Fast development, cheap hosting |
| Prototypes | Quick iteration, simple deployment |
The stack I recommend:
# Create a Vite React projectnpm create vite@latest my-app -- --template react-tscd my-appnpm installFor data fetching, TanStack Query (formerly React Query) gives you everything you need:
import { useQuery } from '@tanstack/react-query'
function Dashboard() { const { data, isLoading, error } = useQuery({ queryKey: ['users'], queryFn: () => fetch('/api/users').then(r => r.json()) })
if (isLoading) return <div>Loading...</div> if (error) return <div>Error: {error.message}</div>
return <UserList users={data} />}Why this works:
- Simpler mental model: No client/server component confusion
- Cheaper hosting: Deploy to any static CDN (Vercel, Netlify, CloudFlare)
- Faster development: No build-time data fetching complexity
- Easier debugging: Everything runs in the browser
A developer on Reddit shared this experience:
“Went for React + Vite + TanStack Query, good ol’ React paradigm, worked like a charm. Easier to compose React components compared to Next.js having to extract components because of client vs server.”
When Next.js Actually Makes Sense
I’m not saying Next.js is bad. I’m saying use it when you need its features.
Use Next.js for:
| Scenario | Why Next.js Helps |
|---|---|
| Public blogs | SEO, fast initial load |
| E-commerce | SEO, product pages |
| Marketing sites | SEO, social sharing |
| News sites | SEO, content-heavy |
| Documentation | SEO, static generation |
The key feature here is server-side rendering (SSR) for SEO:
// Next.js Server Component - runs on the serverasync function BlogPost({ params }: { params: { slug: string } }) { const post = await getPost(params.slug) // Fetches on server
// This HTML is sent to the client with data already populated // Google can index it immediately return ( <article> <h1>{post.title}</h1> <p>{post.content}</p> </article> )}When Google crawls this page, it sees the complete content. With a SPA, Google sees an empty div until JavaScript runs.
Next.js also provides:
- Automatic code splitting (smaller initial bundles)
- Image optimization
- API routes for backend functionality
- Static site generation for fast page loads
These are valuable features for the right use case.
The Real Cost of Over-Engineering
I’ve seen teams suffer from choosing Next.js when they didn’t need it.
Symptom 1: Component schizophrenia
You write a component, then realize it needs state. Now you add “use client”. Then you need to pass data from a server component. Now you’re serializing data or using server actions.
// The complexity spiral// Server Componentasync function Parent() { const data = await fetchData() // Server-side
return ( // Can't pass functions to Client Component // Can't use useState here // Must serialize data as props <Child data={data} /> )}
// Client Component'use client'function Child({ data }) { const [state, setState] = useState() // OK here // But now you're managing two worlds}Symptom 2: Cache confusion
Next.js caching is powerful but complex. I’ve seen developers spend hours debugging stale data issues.
Symptom 3: Infrastructure cost
SPAs deploy to static CDNs for pennies. Next.js apps need Node.js servers or edge runtimes.
SPA Hosting Costs (monthly):- Vercel Free tier: $0- Netlify Free tier: $0- CloudFlare Pages: $0
Next.js SSR Hosting Costs (monthly):- Vercel Pro: $20+- AWS Lambda: Variable- Your own server: $10-50+My Simple Rule
After years of trial and error, I follow this rule:
Start with Vite. Add Next.js only when you can articulate the specific feature you need.
Here’s what that means in practice:
Project Type Start With Add Next.js When...-------------- ---------- -------------------Internal dashboard Vite SPA Never (probably)SaaS application Vite SPA You need public landing pagesPublic blog Next.js ImmediatelyE-commerce Next.js ImmediatelyAdmin panel Vite SPA NeverMarketing site Next.js ImmediatelyCommon Mistakes to Avoid
Mistake 1: Resume-driven development
Don’t choose Next.js because job postings mention it. Choose it because your project needs SSR.
Mistake 2: Future-proofing anxiety
“I might need SSR later” is not a reason to start with Next.js. Migrating from Vite to Next.js is straightforward if you keep your data fetching logic separate.
Mistake 3: Ignoring the basics
Both SPA and Next.js require solid fundamentals:
- Component composition
- State management
- Data fetching patterns
- Error handling
Master these first. The framework choice matters less than your fundamentals.
Quick Comparison
Feature Vite SPA Next.js------- -------- -------Setup complexity Simple ModerateDeployment Static CDN Server required (for SSR)SEO Poor ExcellentInitial load JS required HTML readyDevelopment speed Fast ModerateHosting cost Near zero HigherComponent model One paradigm Client + ServerData fetching Client-side Server + ClientWhat Actually Matters
The right answer depends on your requirements, not marketing hype.
A developer on Reddit put it perfectly:
“Easy solution is to choose stack based on actual requirements and characteristics instead of hype and marketing. Vite SPA is a good starting point. Couple that with some established backend and you got a cheap, boring and working product.”
Cheap, boring, and working. That’s often exactly what you need.
Summary
Choose React SPA with Vite when:
- Your app is behind authentication
- You don’t need SEO
- You want simpler development
- You want cheaper hosting
- You’re building internal tools
Choose Next.js when:
- You need SEO (public content)
- You’re building e-commerce
- You need server-side rendering
- You want built-in optimizations
- You have content-heavy pages
The guilt you feel about not using Next.js? Let it go. Use the right tool for the job, not the tool everyone says you should use.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 Reddit Discussion: Next.js SPA Reality Check
- 👨💻 Vite Official Documentation
- 👨💻 Next.js Official Documentation
- 👨💻 TanStack Query Documentation
- 👨💻 React Documentation
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments