Building a Simple Blog App with Express, Prisma, and PostgreSQL
In this tutorial, I will take you step by step to building a simple(CRUD) blog application. The app will support creating, retrieving, updating, and deleting blog posts.
Prerequisites
Make sure you have Node.js and npm installed on your machine, and you have PostgreSQL set up with a database.
I hope you know how to setup a Postgres databaseπππ. If you don't You have toπ,
Let's Dive Right in
Step 1: Project Setup
Create a new directory for your project and initialize it with npm:
mkdir prisma-express-blog-app
cd prisma-express-blog-app
npm init -y
Step 2: We'll Install Our Project Dependencies
npm install express @prisma/client dotenv
Step 3: We'll Set Up Prisma
npx prisma init
This would install the necessary files and folders for prisma
Step 4: We'll configure our prisma schema to look like this
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// Post model represents individual blog posts
model Post {
id Int @id @default(autoincrement())
title String
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
Step 5: We'll Configure our .env file to contain our postgres database URL. Mine looks like this
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
I'll edit that and add my postgresDb URL
DATABASE_URL="postgresql://postgres:qwer@localhost:5432/mydb?schema=public"
You'll change your password and database name
Step 6: We'll Create A Database Migration
npx prisma migrate dev
This would create a migration for you and add the folder, when you open the folder you see your migration.sql file which looks exactly like your schema
-- CreateTable
CREATE TABLE "Post" (
"id" SERIAL NOT NULL,
"title" TEXT NOT NULL,
"content" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "Post_pkey" PRIMARY KEY ("id")
);
Step 7: Now we'll create our main entry file and call it app.js
.
We'll initialize express, dotenv our middleware and also listen to our port
const express = require("express"); require("dotenv").config();
const app = express();
app.use(express.json());
const port = process.env.PORT || 3000;
app.get("/", (req, res) => {
res.send("Welcome Tou Prisma, Express And PSQL Tutorial");
});
app.listen(port, () => {
console.log(Server listening on ${port}
);
});
## Step 8: Now lets import prismaClient and configure it, add this lines of code to your `app.js` file
```javascript
const { PrismaClient } = require('@prisma/client')
const prisma = new PrismaClient();
Step 9: Now we add our first route, which would be to add a blog
This route would look like this:
app.post("/post", async (req, res) => { try { const { title, content } = req.body; if (!title || !content) { return res .status(400) .json({ message: "Please input Title Anc Content" }); }
const blog = await prisma.post.create({
data: { title, content },
});
return res
.status(201)
.json({ message: "Blog created successfully", data: blog });
} catch (error) {
return res.status(500).json({ message: "Error creating blog" });
}
});
After adding this to your `app.js` file we should test that route before moving on, my route looks like this `http://localhost:4500/post`
> I got my response after testing
![Create Post](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vju5s5b93fi961a5ypzb.png)
> Add as much Blogs as Possible
## Step 10: Stretch Your Fingers ππ
![Stretch](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ftkqox4dpbtnaihd0o4g.gif)
## Step 11: Now we'll add a Route to get all Blogs and tell us the number of blogs available
```javascript
app.get("/posts", async (req, res) => {
try {
const blogs = await prisma.post.findMany();
return res.status(201).json({ data: blogs.length, blogs });
} catch (error) {
return res.status(500).json({ message: "Error fetching blogs" });
}
});
after testing:
Step 12: We'll add a route to get a single blog by title
app.get("/get", async (req, res) => {
const { title } = req.query;
try {
const blog = await prisma.post.findFirst({
where: { title }
});
if (blog) {
return res.status(200).json(blog);
} else {
return res.status(404).json({ message: "Blog not found" });
}
} catch (error) {
console.log(error);
return res.status(500).json({ message: "Error fetching blog" });
}
});
Step 13: I'll add some more routes, you can add and test for yourself
Now I finally have this:
const express = require("express"); const { PrismaClient } = require("@prisma/client"); require("dotenv").config();
const prisma = new PrismaClient();
const app = express();
app.use(express.json());
const port = process.env.PORT || 3000;
app.get("/", (req, res) => {
res.send("Welcome to Prisma, Express, and PSQL Tutorial");
});
// Create a blog
app.post("/post", async (req, res) => {
try {
const { title, content } = req.body;
if (!title || !content) {
return res
.status(400)
.json({ message: "Please input Title and Content" });
}
const blog = await prisma.post.create({
data: { title, content },
});
return res
.status(201)
.json({ message: "Blog created successfully", data: blog });
} catch (error) {
return res.status(500).json({ message: "Error creating blog" });
}
});
// Get all blogs
app.get("/posts", async (req, res) => {
try {
const blogs = await prisma.post.findMany();
return res.status(201).json({ data: blogs.length, blogs });
} catch (error) {
return res.status(500).json({ message: "Error fetching blogs" });
}
});
// Get a single blog by title
app.get("/get", async (req, res) => {
const { title } = req.query;
try {
const blog = await prisma.post.findFirst({
where: { title }
});
if (blog) {
return res.status(200).json(blog);
} else {
return res.status(404).json({ message: "Blog not found" });
}
} catch (error) {
console.log(error);
return res.status(500).json({ message: "Error fetching blog" });
}
});
// Update a blog by id
app.put("/post/:id", async (req, res) => {
const { id } = req.params;
const { title, content } = req.body;
try {
const updatedBlog = await prisma.post.update({
where: { id: parseInt(id) },
data: { title, content },
});
return res.json({
message: "Blog updated successfully",
data: updatedBlog,
});
} catch (error) {
console.log(error);
return res.status(500).json({ message: "Error updating blog" });
}
});
// Delete a blog by id
app.delete("/post/:id", async (req, res) => {
const { id } = req.params;
try {
await prisma.post.delete({
where: { id: parseInt(id) },
});
return res.json({ message: "Blog deleted successfully" });
} catch (error) {
return res.status(500).json({ message: "Error deleting blog" });
}
});
app.listen(port, () => {
console.log(Server listening on ${port}
);
});
> And that is a comprehensive CRUD app using Prisma, PSQL, and express
[Link to Github Repo Containing The Code](https://github.com/FredAbod/Prisma-Tutorial)
## Thank you for taking the time to read π₯°π₯°, I hope this was helpful, Don't Forget to drop a like and followππ. See You on the Next Oneπ€
![Bow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2go8l3113h2kw6enp2d5.gif)
Top comments (1)
good job just easy way to read