Next.js Server Actions Integration with MySQL to Build a CRUD App
Next.js 13+ introduces Server Actions, an innovative feature that simplifies server-side logic handling while keeping API calls efficient. When combined with MySQL, this enables developers to build powerful, server-drive
Next.js 13+ introduces **Server Actions**, an innovative feature that simplifies server-side logic handling while keeping API calls efficient. When combined with **MySQL**, this enables developers to build powerful, server-driven applications with optimized database interactions.
In this blog post, we'll walk through **integrating Next.js Server Actions with MySQL** to create a **CRUD (Create, Read, Update, Delete) application**.
* * *
## **Why Use Server Actions in Next.js?**
Traditionally, Next.js applications required API routes (`pages/api` or `app/api`) for server-side logic. With **Server Actions**, you can now handle form submissions and data mutations directly in the component without creating separate API endpoints.
### **Benefits of Server Actions**
* **Simplified codebase**: No need for additional API routes.
* **Improved performance**: Direct server-side execution reduces unnecessary client-server interactions.
* **Built-in security**: Avoids exposing database credentials in the client.
* * *
## **Step 1: Setting Up a Next.js Project**
First, create a new Next.js project with TypeScript enabled:
```sh
npx create-next-app@latest my-next-crud-app --typescript
cd my-next-crud-app
```
* * *
## **Step 2: Install MySQL and Prisma ORM**
To interact with MySQL, we’ll use **Prisma**, a powerful ORM for managing database queries in TypeScript.
### **Install Dependencies**
```sh
npm install mysql2 @prisma/client
npm install --save-dev prisma
```
### **Initialize Prisma**
Run the following command to generate a Prisma configuration:
```sh
npx prisma init
```
This will create a `.env` file and a `prisma/schema.prisma` file.
* * *
## **Step 3: Configure MySQL Connection**
In your `.env` file, update the **DATABASE\_URL** with your MySQL credentials:
```env
DATABASE_URL="mysql://user:password@localhost:3306/mydatabase"
```
Replace:
* `user` with your MySQL username.
* `password` with your MySQL password.
* `mydatabase` with the database name.
* * *
## **Step 4: Define a Prisma Model**
Edit `prisma/schema.prisma` to define a **User** model:
```prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
name String
email String @unique
createdAt DateTime @default(now())
}
```
Now, apply the changes to your database:
```sh
npx prisma migrate dev --name init
```
* * *
## **Step 5: Implement Server Actions for CRUD Operations**
### **1\. Create a User**
In `app/actions.ts`, define a **server action** to insert a new user.
```typescript
"use server";
import prisma from "@/lib/prisma";
export async function createUser(formData: FormData) {
const name = formData.get("name") as string;
const email = formData.get("email") as string;
await prisma.user.create({
data: { name, email },
});
return { message: "User created successfully" };
}
```
### **2\. Read Users**
In `app/actions.ts`, define a function to fetch users.
```typescript
export async function getUsers() {
return await prisma.user.findMany();
}
```
### **3\. Update a User**
```typescript
export async function updateUser(id: number, name: string) {
return await prisma.user.update({
where: { id },
data: { name },
});
}
```
### **4\. Delete a User**
```typescript
export async function deleteUser(id: number) {
return await prisma.user.delete({ where: { id } });
}
```
* * *
## **Step 6: Build the Next.js UI with Server Actions**
### **User Form Component**
In `app/page.tsx`, add a simple form to create users.
```tsx
"use client";
import { useState } from "react";
import { createUser } from "./actions";
export default function Home() {
const [message, setMessage] = useState("");
async function handleSubmit(event: React.FormEvent) {
event.preventDefault();
const formData = new FormData(event.target as HTMLFormElement);
const response = await createUser(formData);
setMessage(response.message);
}
return (
Next.js MySQL CRUD
{message &&
{message}
}
);
}
```
* * *
## **Step 7: Display Users in a List**
Modify `app/page.tsx` to display users:
```tsx
import { getUsers, deleteUser } from "./actions";
export default async function UserList() {
const users = await getUsers();
async function handleDelete(id: number) {
await deleteUser(id);
}
return (
Users List
{users.map((user) => (
{user.name} ({user.email})
))}
);
}
```
* * *
## **Step 8: Testing and Running the App**
To start your Next.js app, run:
```sh
npm run dev
```
Visit `http://localhost:3000` to interact with the CRUD application.
* * *
## **Conclusion**
With **Next.js Server Actions and MySQL**, we built a simple CRUD application while keeping the backend logic minimal. Server Actions simplify API handling, reduce client-server interactions, and improve security by avoiding direct exposure of database logic.
## Follow me on:
X: [@maxiujun](https://x.com/maxiujun)
Threads.net [@xiujunma](https://www.threads.net/@xiujunma)
BlueSky: [@maxiujun.bsky.social](https://bsky.app/profile/maxiujun.bsky.social)