
Building Full Stack CRUD App with PostgreSQL
Are you just getting started with full stack development and want to build your first CRUD (Create, Read, Update, Delete) app using a real database like PostgreSQL? You're in the right place!
🚀 What We'll Build
- Add a new book
- View all books
- Edit book details
- Delete a book
🧱 Step 1: Setup the Backend
📁 Create Project Folder
mkdir book-manager
cd book-manager
npm init -y
📦 Install Dependencies
npm install express cors dotenv prisma @prisma/client
⚙️ Initialize Prisma
npx prisma init
🔗 Update .env
DATABASE_URL="postgresql://youruser:yourpassword@localhost:5432/bookmanager"
📐 Step 2: Define Prisma Schema
model Book {
id Int @id @default(autoincrement())
title String
author String
createdAt DateTime @default(now())
}
npx prisma migrate dev --name init
npx prisma generate
🧠 Step 3: Create Express Server
const express = require('express');
const cors = require('cors');
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
const app = express();
app.use(cors());
app.use(express.json());
app.get('/books', async (req, res) => {
const books = await prisma.book.findMany();
res.json(books);
});
app.post('/books', async (req, res) => {
const { title, author } = req.body;
const book = await prisma.book.create({ data: { title, author } });
res.json(book);
});
app.put('/books/:id', async (req, res) => {
const { title, author } = req.body;
const { id } = req.params;
const book = await prisma.book.update({
where: { id: parseInt(id) },
data: { title, author }
});
res.json(book);
});
app.delete('/books/:id', async (req, res) => {
const { id } = req.params;
await prisma.book.delete({ where: { id: parseInt(id) } });
res.json({ message: 'Book deleted' });
});
app.listen(4000, () => console.log('Server running on http://localhost:4000'));
🌐 Step 4: Set Up React Frontend
npm create vite@latest book-client --template react
cd book-client
npm install axios
npm run dev
🖼️ Step 5: Build the UI
import { useEffect, useState } from 'react';
import axios from 'axios';
const API = 'http://localhost:4000/books';
function App() {
const [books, setBooks] = useState([]);
const [form, setForm] = useState({ title: '', author: '', id: null });
const fetchBooks = async () => {
const res = await axios.get(API);
setBooks(res.data);
};
useEffect(() => {
fetchBooks();
}, []);
const handleSubmit = async (e) => {
e.preventDefault();
if (form.id) {
await axios.put(`${API}/${form.id}`, form);
} else {
await axios.post(API, form);
}
setForm({ title: '', author: '', id: null });
fetchBooks();
};
const handleEdit = (book) => {
setForm(book);
};
const handleDelete = async (id) => {
await axios.delete(`${API}/${id}`);
fetchBooks();
};
return (
<div className="container" style={{ padding: "20px", maxWidth: "600px", margin: "auto" }}>
<h2>📚 Book Manager</h2>
<form onSubmit={handleSubmit}>
<input placeholder="Title" value={form.title} onChange={(e) => setForm({ ...form, title: e.target.value })} required />
<input placeholder="Author" value={form.author} onChange={(e) => setForm({ ...form, author: e.target.value })} required />
<button type="submit">{form.id ? 'Update' : 'Add'} Book</button>
</form>
<ul>
{books.map((b) => (
<li key={b.id}>
<strong>{b.title}</strong> by {b.author}
<button onClick={() => handleEdit(b)}>Edit</button>
<button onClick={() => handleDelete(b.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
export default App;
🧪 Step 6: Test It All Together
- Start PostgreSQL
- Run the backend:
node index.js
- Run the frontend:
npm run dev
🎯 Conclusion
You’ve just built a complete full stack CRUD app with PostgreSQL, Node.js, Express, React, and Prisma!
Now that you’ve mastered the basics, try adding user authentication, search functionality, or deploy your app to production.
💬 What’s Next?
If you found this helpful:
- 👉 Comment below your thoughts or questions
- 🔗 Share it with your fellow devs
- 📬 Subscribe to CodeJourneyWithAamir for more tutorials!
Hi Everyone, please do not spam in comments.