The full-stack JavaScript ecosystem is in a constant state of flux, with developers seeking the perfect balance of productivity, performance, and scalability. Frameworks like Next.js, Remix, and RedwoodJS have set high standards, each offering a unique philosophy on building modern web applications. Amidst this landscape, Blitz.js carved out a niche with its promise of a “Zero-API” layer, bringing a Ruby on Rails-like developer experience to the React world. However, like the ecosystem it inhabits, Blitz.js has undergone a significant transformation. This evolution is a key topic in recent Blitz.js News and has major implications for full-stack development.
This article delves into the evolution of Blitz.js, charting its journey from an opinionated, monolithic framework to a flexible, powerful toolkit that supercharges standard Next.js applications. We’ll explore the core concepts behind this pivot, provide practical code examples for implementing the modern Blitz toolkit, and discuss advanced techniques and best practices. Whether you’re a seasoned Blitz developer or a newcomer exploring the latest in React News, understanding this shift is crucial for building next-generation full-stack applications with unparalleled efficiency.
The “Zero-API” Dream and The New Reality
To understand where Blitz.js is heading, we must first appreciate where it came from. Its initial value proposition was radical and compelling: eliminate the need to write REST or GraphQL APIs for your front-end to communicate with your back-end. This was the “Zero-API” data layer.
The Original Vision: RPC and Convention over Configuration
The original Blitz.js was a fork of Next.js that came with a built-in Remote Procedure Call (RPC) mechanism. You could define a query or mutation as a simple asynchronous function on the server, and then import and call it directly within your React components as if it were a local function. Blitz handled all the underlying serialization, HTTP requests, and data fetching automatically.
This approach dramatically reduced boilerplate and cognitive overhead. Instead of managing API endpoints, client-side fetching libraries, and data transformation logic, you could focus purely on your application’s business logic. A typical mutation looked deceptively simple, abstracting away the network layer entirely.
// Old Blitz.js (v1) Example: app/projects/mutations/createProject.js
import { Ctx } from "blitz";
import db from "db";
import { z } from "zod";
const CreateProject = z.object({
name: z.string().min(3),
});
export default async function createProject(input, ctx: Ctx) {
ctx.session.$authorize(); // Built-in authorization
const data = CreateProject.parse(input);
const project = await db.project.create({
data: {
name: data.name,
userId: ctx.session.userId,
},
});
return project;
}
The Shift: Embracing the Next.js Ecosystem
While powerful, maintaining a full fork of a rapidly evolving framework like Next.js presented significant challenges. As the official Next.js News announced features like Middleware, the App Router, and deeper Vercel integrations, the maintenance burden for the Blitz team grew. The community realized that the true magic of Blitz wasn’t the fork itself, but its Zero-API data layer and authentication system.
This led to a strategic pivot: unbundle Blitz.js. Instead of a monolithic framework, Blitz evolved into a collection of standalone libraries that can be installed in *any* Next.js application. This new approach offers the best of both worlds: the full power and support of the mainstream Next.js ecosystem, enhanced with the productivity-boosting features of Blitz. This modularity also opens the door for interesting future integrations, a hot topic in Remix News and the broader full-stack community.
Core Components of the New Blitz.js
The modern Blitz.js is not a single install but a suite of tools you can adopt incrementally. The two primary packages are blitz-rpc
for the data layer and blitz-auth
for authentication, forming a robust foundation for any full-stack project.

The Standalone Blitz RPC Layer
The core of the Zero-API experience now lives in the @blitzjs/rpc
package. It provides the same delightful developer experience of calling server code from the client, but it integrates seamlessly with the standard Next.js API routes (both in the pages
and app
directories). You simply create a single API endpoint to handle all your RPC calls.
Setting this up is straightforward. You define your queries and mutations as before, but now you wire them up through a dedicated API route handler. This handler acts as a single entry point for all your server-side functions.
// Modern Blitz Setup: src/pages/api/rpc/[[...blitz]].ts
import { rpcHandler } from "@blitzjs/rpc";
import { api } from "src/blitz-server";
import { getSession } from "@blitzjs/auth";
import db from "db";
// Define queries and mutations in separate files
// e.g., src/projects/queries/getProjects.ts
// e.g., src/projects/mutations/createProject.ts
export default api(
rpcHandler({
// This onError handler is a great place for logging
onError: (error, { req, res }) => {
console.error(error);
},
// This middleware function runs before every RPC call
middleware: [
async (req, res, next) => {
// Example: Attach session and db to the context
const session = await getSession(req, res);
res.blitzCtx = {
session,
db,
};
await next();
},
],
})
);
This approach is more explicit and aligns perfectly with Next.js conventions, making it easier to understand and debug. It also integrates beautifully with data-fetching libraries, which is a constant point of discussion in React Query News and for users of tools like Apollo Client or Urql.
Flexible and Secure Authentication with `blitz-auth`
Authentication is another area where Blitz shines. The @blitzjs/auth
package provides a complete, session-based authentication solution that is both secure and easy to use. It handles everything from password hashing and secure session management to CSRF protection out of the box. It’s a powerful alternative to other popular solutions like NextAuth.js.
Because it’s a standalone package, you have full control over the database schema and login/signup logic. It provides a set of utilities that you integrate into your own API routes and components, offering a great balance of convention and configuration.
Advanced Techniques and Integrations
The true power of the new Blitz toolkit is revealed when you combine it with other best-in-class libraries from the React ecosystem. Its un-opinionated nature makes it a perfect companion for modern state management, form handling, and testing tools.
Integrating with Modern State Management
The Blitz RPC client is built on top of React Query, providing a world-class data-fetching and caching experience out of the box. When you call a `useQuery` or `useMutation` hook from `@blitzjs/rpc`, you are getting all the power of React Query—caching, refetching, optimistic updates, and more—without any extra configuration.
Here’s how you would use a Blitz query in a React component to fetch a list of projects:
// src/projects/components/ProjectList.tsx
import { useQuery } from "@blitzjs/rpc";
import getProjects from "src/projects/queries/getProjects";
import { Suspense } from "react";
function Projects() {
// This hook calls the server function and manages data fetching state
const [projects] = useQuery(getProjects, { status: "active" });
return (
<ul>
{projects.map((project) => (
<li key={project.id}>{project.name}</li>
))}
</ul>
);
}
function ProjectList() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Projects />
</Suspense>
);
}
export default ProjectList;
This seamless integration is a game-changer. While Blitz handles the transport layer, you can leverage other state managers like Zustand, Jotai, or Recoil for managing global UI state, creating a clean separation of concerns. This flexibility is a significant advantage over more monolithic approaches.

Testing Your Blitz Endpoints
A common question with “magic” frameworks is: “How do I test this?” The beauty of Blitz’s RPC approach is that your queries and mutations are just standard JavaScript functions. They can be unit-tested easily with tools like Jest or Vitest, without needing to spin up a server. You can mock the database and session context to test your business logic in isolation.
This aligns with modern testing best practices seen in Jest News and with tools like React Testing Library, ensuring your application is robust and maintainable.
// src/projects/mutations/createProject.test.ts
import { vi, test, expect } from "vitest";
import createProject from "./createProject";
// Mock the database and session context
const mockDb = {
project: {
create: vi.fn().mockResolvedValue({ id: 1, name: "Test Project", userId: 123 }),
},
};
const mockCtx = {
session: {
$authorize: vi.fn(),
userId: 123,
},
db: mockDb,
};
test("createProject should create a new project", async () => {
const input = { name: "Test Project" };
const project = await createProject(input, mockCtx as any);
// Assert that authorization was checked
expect(mockCtx.session.$authorize).toHaveBeenCalled();
// Assert that the database was called with the correct data
expect(mockDb.project.create).toHaveBeenCalledWith({
data: {
name: "Test Project",
userId: 123,
},
});
// Assert that the function returns the created project
expect(project.name).toBe("Test Project");
});
Best Practices and the Road Ahead
As you adopt the modern Blitz toolkit, a few best practices can help you build scalable and maintainable applications. The future of the toolkit also looks bright, with potential for even broader integration across the JavaScript ecosystem.
Structuring Your Blitz-powered App
With great flexibility comes the need for smart conventions. A recommended practice is to co-locate your Blitz functions (queries, mutations) with the features they belong to. For example:

src/features/auth/mutations/login.ts
src/features/auth/mutations/signup.ts
src/features/projects/queries/getProjects.ts
src/features/projects/queries/getProject.ts
Additionally, always validate input data on the server using a library like Zod. This ensures data integrity and provides clear error messages, a pattern that is also popular in the tRPC community and a frequent topic for those following React Hook Form News, as it simplifies form validation from end to end.
The Future: Beyond Next.js?
The modularization of Blitz.js opens up exciting possibilities. The core RPC and auth libraries are, in theory, platform-agnostic. This means we could see official support for other frameworks in the future. Imagine using Blitz RPC in a Remix application or even a serverless function. There’s also immense potential in the mobile space; a version of the Blitz client could dramatically simplify data fetching in React Native apps, which would be significant React Native News for developers using tools like Expo.
As the React ecosystem continues to embrace server-centric patterns like React Server Components, Blitz’s RPC architecture is perfectly positioned. It provides a clear, type-safe bridge between server and client, which will become even more valuable in this new paradigm.
Conclusion: A New Chapter for Blitz.js
Blitz.js has successfully navigated a challenging but necessary evolution. By shedding its monolithic structure and embracing a modular, toolkit-based approach, it has transformed from a niche framework into a powerful set of libraries that enhance the world’s most popular React framework, Next.js. This pivot ensures long-term viability and allows developers to leverage the best of both worlds: the massive, innovative Next.js ecosystem and the unparalleled developer experience of Blitz’s Zero-API data layer.
The key takeaways are clear: Blitz.js is more flexible, powerful, and better integrated with the modern web ecosystem than ever before. It retains its core promise of simplifying full-stack development while granting developers the freedom to choose their own tools and architecture. For anyone building with Next.js, the new Blitz toolkit is not just a piece of Blitz.js News—it’s an essential set of tools to consider for your next project.