Why I Switched from Next.js to TanStack Start, Shadcn UI v2, and Better Auth
After growing frustrated with Next.js’s breaking changes, complex server components, and Vercel lock‑in, the author explores a new stack—TanStack Start, shadcn/ui v2, and Better Auth—detailing their features, code examples, and why they may be a superior alternative for modern React development.
TanStack Start – A Next.js Alternative
TanStack Start is a full‑stack React framework that bundles React 19, Vite 7, file‑based routing, and built‑in SSR/SSG. It removes the need for a specific deployment platform and eliminates the "use client" directive requirement.
React 19 with server components and actions
Vite 7 as the bundler (no Webpack)
File‑based routing with intuitive conventions
SSR/SSG support out of the box
Typical entry point:
// src/routes/+page.tsx
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/")({
component: HomePage,
});
function HomePage() {
return <div>Hello, freedom!</div>;
}shadcn/ui v2 – Component Library
shadcn/ui v2 provides copy‑and‑paste components that you own completely. It uses Tailwind 4 and a CSS‑variable‑based theming system, removing the need for JavaScript theme providers.
:root {
--primary: oklch(0.55 0.22 25);
--primary-foreground: oklch(0.98 0.01 25);
}
.dark {
--primary: oklch(0.65 0.20 25);
}Key quality attributes include proper focus management, keyboard navigation, native‑like animations, and built‑in dark mode.
Better Auth – Type‑First Authentication
Better Auth is a framework‑agnostic TypeScript library that offers out‑of‑the‑box OAuth provider support and lets you store sessions in any database.
Works with React, Next.js, Remix, etc.
Built‑in OAuth (Google, GitHub, …)
Type‑safe API for sign‑in and session handling
Session storage via custom adapters (e.g., Prisma)
Google OAuth configuration example:
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
export const auth = betterAuth({
database: prismaAdapter(prisma, { provider: "postgresql" }),
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
},
},
});
// client side
import { signIn, useSession } from "@/lib/auth-client";
await signIn.social({ provider: "google" });
const { data: session } = useSession();First‑time OAuth users are automatically registered, eliminating a separate registration flow.
Project Structure Example
src/
├── components/
│ ├── ui/ # shadcn components
│ ├── mode-toggle.tsx
│ └── user-menu.tsx
├── lib/
│ ├── auth.ts # Better Auth server config
│ ├── auth-client.ts # client helpers
│ └── utils.ts
├── routes/
│ ├── api/auth/$.ts # Auth API handler
│ ├── __root.tsx
│ ├── index.tsx
│ └── login.tsx
└── styles.css # Tailwind + CSS variablesAll files are colocated, typed, and benefit from fast Vite development builds.
When to Consider Switching
Developers may switch from Next.js if they encounter any of the following pain points:
Frequent breaking changes in the App Router
Unclear boundaries between server and client components
Perceived lock‑in to Vercel’s hosting platform
Slow development build times
If these issues affect productivity, TanStack Start combined with shadcn/ui v2 and Better Auth offers a more flexible, performant, and developer‑friendly stack while remaining fully compatible with the broader React ecosystem.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
