Next.js 15 & Server Actions
Stability has arrived. The App Router is no longer an experiment, and Server Actions have fundamentally changed how we manipulate data on the web.
React Server Components (RSC) have been the biggest paradigm shift in the React ecosystem since hooks. For the last couple of years, the community has been in a state of transition, figuring out the best practices for this new hybrid model. With Next.js 15, the dust has settled.
The Death of the API Route?
Not quite, but close. For internal application logic, Server Actions are the new default. They allow us to define functions that run securely on the server and call them directly from our frontend components, mimicking the simplicity of a function call.
Consider a simple newsletter signup. In the "old" world, you'd create an API route at
/api/subscribe, validating the request, and responding with JSON. In your client component,
you'd have to manage loading states, error handling, and fetch calls.
The New Way
// action.ts
'use server'
export async function subscribe(formData: FormData) {
const email = formData.get('email')
await db.user.create({ email })
revalidatePath('/')
}
// component.tsx
import { subscribe } from './action'
export default function Signup() {
return (
<form action={subscribe}>
<input name="email" />
<button type="submit">Join</button>
</form>
)
}
This snippet runs without JavaScript enabled on the client. It handles the POST request, the database operation, and even cache revalidation. It's PHP-level simplicity with the power of the React component model.
Partial Prerendering (PPR)
Next.js 15 also doubles down on Partial Prerendering. This feature addresses a common complaint with Server Components: the trade-off between static speed and dynamic personalization.
Historically, a page was either statically built at deploy time (fast, but generic) or dynamic at request time (personalized, but slower TTFB). PPR allows us to mix the two in a single response.
The server sends the static shell instantly (like an Edge CDN response) while simultaneously streaming in the dynamic parts (like user profile info) as they become ready. It creates a perceived loading speed that feels instant, even for highly dynamic apps.
Caching Changes
One of the most controversial aspects of Next.js 14 was its aggressive caching defaults. Fetch requests were cached by default, leading to stale data confusion.
Next.js 15 flips this on its head. Fetch requests are now uncached by default (`no-store`). This is a massive win for developer experience. "Why is my data old?" was the number one question in Discord channels. Now, you opt-in to caching when you need performance, rather than opting-out to get fresh data.
Conclusion
The framework is maturing. The focus is shifting from shipping shiny new primitives to refining the developer experience and stability. If you've been waiting on the sidelines for the App Router to stabilize, now is the time to jump in.