Next.js 15 brought some big changes to how we build React apps. After migrating a project from the Pages Router, here's what stood out.
The biggest shift is that components are server-rendered by default. This means you can fetch data directly inside a component without any useEffect or loading state.
export default async function Page() {
const data = await fetchSomething();
return <div>{data.title}</div>;
}No more getServerSideProps. The component is the data fetcher.
'use client'You only need 'use client' when a component uses:
window, localStorage)Everything else can stay on the server, which means smaller JS bundles.
I over-used 'use client' at first out of habit. The real win comes from keeping as much as possible on the server and only pushing interactivity to the leaves of the component tree.
It takes some getting used to, but once it clicks it feels natural.