We use cookies.

Modern web development moves fast and building scalable applications requires tools that work together smoothly. After working with many frameworks, databases, deployment platforms, and architectural patterns, I have refined a stack that has become my primary choice for real world production projects. It focuses on performance, developer experience, and predictable architecture.
This article covers each part of that stack with practical explanations and implementation details. It includes Turborepo, Next.js with Server Actions, Prisma 7, Neon PostgreSQL, TanStack Query, Cloudinary, Better Auth or NextAuth, and deployment to Vercel with standalone output.
Turborepo provides a scalable foundation by grouping all related projects and shared packages inside one monorepo.
apps/
web/ Next.js application
packages/
ui/ Shared UI components
db/ Prisma schema and client
utils/ Shared utilities
Next.js is the core of this stack. The App Router adds structured layouts, while Server Actions remove the need for separate API layers in most cases.
"use server";
import { prisma } from "@/packages/db/prisma";
export async function createTask(data: { title: string }) {
return prisma.task.create({ data });
}
TypeScript eliminates many classes of runtime bugs and makes refactoring safer. Prisma generates typed models and TanStack Query infers types, creating a fully typed chain from database to UI.
Prisma 7 introduced major improvements that make it ideal for cloud native environments.
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Task {
id String @id @default(cuid())
title String
createdAt DateTime @default(now())
}
import { PrismaClient } from "@prisma/client";
declare global {
var __prisma: PrismaClient | undefined;
}
export const prisma =
global.__prisma ??
new PrismaClient({
log: ["query", "warn", "error"]
});
if (process.env.NODE_ENV !== "production") {
global.__prisma = prisma;
}
Both NextAuth and Better Auth integrate naturally with the Next.js App Router.
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";
export const handler = NextAuth({
providers: [GitHub],
session: { strategy: "jwt" }
});
export { handler as GET, handler as POST };
TanStack Query handles caching and server state synchronization. It replaces unnecessary global state for data that comes from APIs or the database.
const query = useQuery({
queryKey: ["tasks"],
queryFn: async () => {
const res = await fetch("/api/tasks");
return res.json();
}
});
const mutation = useMutation({
mutationFn: createTask,
onSuccess: () => queryClient.invalidateQueries(["tasks"])
});
Cloudinary is used for all media because it supports on the fly transformations, responsive formats, and global CDN delivery.
import { v2 as cloudinary } from "cloudinary";
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD,
api_key: process.env.CLOUDINARY_KEY,
api_secret: process.env.CLOUDINARY_SECRET
});
export async function POST(req: Request) {
const { file } = await req.json();
const upload = await cloudinary.uploader.upload(file, {
folder: "myapp"
});
return Response.json(upload);
}
Vercel is the ideal deployment environment for this stack.
/** @type {import('next').NextConfig} */
module.exports = {
output: "standalone",
images: {
domains: ["res.cloudinary.com"]
}
};
This stack forms a complete, production ready foundation for modern web applications.
Each tool solves a specific problem without adding unnecessary complexity. Together they create a fast, predictable, and maintainable development workflow.