In this workshop, you'll learn how to create an MVP web app using Next.js, Prisma, and React. We'll cover setting up your environment, creating a web app, setting up a database, creating a new React component, saving and retrieving data, and adding some basic styling.
- Setup and Installation
- Create the Web App
- Database Setup
- Create a new React component
- Save and Retrieve the Data
- Add some styling in CSS
- Publish app to a real URL (Optional)
- Open
Terminal
on Mac or Linux, orPowershell
on Windows. - Install Node.js for running JavaScript code
- Install VS Code for writing and editing code
- Create a new Next.js app:
npx create-next-app@latest tsb-hackathon-mvp
Let's use these simple settings to configure the app!
✔ Would you like to use TypeScript? No
✔ Would you like to use ESLint? Yes
✔ Would you like to use Tailwind CSS? No
✔ Would you like to use `src/` directory? Yes
✔ Would you like to use App Router? (recommended) Yes
✔ Would you like to customize the default import alias (@/*)? No
cd tsb-hackathon-mvp
- Install Prisma to help manage database schema and migrations.
npm i prisma --save-dev
npx prisma init --datasource-provider sqlite
npm i --save-dev @types/node
Open the tsb-hackathon-mvp
folder in VS Code.
- Add a
Tweet
data model schema at the end of/prisma/schema.prisma
.
model Tweet {
id Int @id @default(autoincrement())
content String
timestamp DateTime @default(now())
}
- Run the migration to use the database schema
npx prisma migrate dev --name init
Everytime you update and change the database schema, you need to run the migration command to update the database, however run it with a new name each time and use a name that indicates what changes you made.
- Create a
src/db.ts
file to set up the database connection. This file will be used to create a new Prisma client instance and export it as a default module. Prisma is a database toolkit that makes it easy to work with databases in a type-safe way.
import { PrismaClient } from "@prisma/client";
const prismaClientSingleton = () => {
return new PrismaClient();
};
declare global {
var prisma: undefined | ReturnType<typeof prismaClientSingleton>;
}
const prisma = globalThis.prisma ?? prismaClientSingleton();
export default prisma;
if (process.env.NODE_ENV !== "production") globalThis.prisma = prisma;
- Start the web app
npm run dev
Go to http://localhost:3000 to see the web app.
- Create a new folder
src/app/new
and a new filepage.jsx
inside it.
The way NextJS works is if you create a new folder inside the pages
folder, it will create a new route for you. For example, if you create a new folder called new
and a new file called page.jsx
inside it, you can access the new page by going to http://localhost:3000/new
.
- Add a new React component to the new file.
import Link from "next/link";
import prisma from "../../db";
async function createTweet(data) {
"use server";
}
export default function NewTweetPage() {
return (
<div className="container">
<h1>New Tweet</h1>
<Link href="/">Back</Link>
<form action={createTweet}>
<input type="text" name="content" />
<button type="submit">Tweet</button>
</form>
</div>
);
}
- Add a link to the new page in the
src/app/page.js
file. Feel free to replace the entire file with this code.
import Link from "next/link";
export default async function Page() {
return (
<div className="container">
<h1>Mini Twitter</h1>
<Link href="/new">New Tweet</Link>
</div>
);
}
- Delete Unnecessary Files. Delete
page.module.css
. Openglobal.css
and delete everything inside it. (Keep the file, we will add some custom styles later.)
- In the
/src/app/page.js
file, import Prisma:import prisma from "../db";
- Use the Prisma client,
prisma.tweet.findMany()
, to get the tweets from the database.
import Link from "next/link";
import prisma from "../db";
export default async function Page() {
const tweets = await prisma.tweet.findMany();
return (
<div className="container">
<h1>Mini Twitter</h1>
<Link href="/new">New Tweet</Link>
<ul>
{tweets.map((tweet) => (
<div className="tweet" key={tweet.id}>
{tweet.content}
</div>
))}
</ul>
</div>
);
}
- In the
/src/app/new/page.jsx
file, import Prisma:import prisma from "../../db";
andimport { redirect } from "next/navigation";
- Update the createTweet function to create a new tweet.
async function createTweet(data) {
"use server";
const content = data.get("content")?.valueOf();
if (typeof content !== "string" || content.length === 0) {
return;
}
await prisma.tweet.create({
data: {
content,
},
});
redirect("/");
}
- Delete everything in
globals.css
and add these custom styles to get started. Edit the styling to your liking! If you want to add styling around any component, all you need to do is addclassName="your-variable-name"
to thediv
, then come here and add.your-variable-name {}
to the CSS file.
.container {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
.button {
display: flex;
align-items: center;
justify-content: center;
padding: 8px 16px;
width: auto;
color: #fff;
border: none;
border-radius: 8px;
background-color: #1da1f2;
cursor: pointer;
transition: background-color 0.3s;
}
.tweet {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
margin: 16px;
}
Here are some additional styles you can add to the .tweet
class, feel free to customize it to your liking! Choose your own colors, fonts, and sizes.
padding: 16px;
width: 300px;
color: #333;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
border-radius: 8px;
background-color: #fff;
border: 1px solid #e1e8ed;
font-size: 16px;
font-weight: 400;
font-family: "Arial", sans-serif;
You can follow this tutorial to deploy to a real URL using Vercel: Next.js Tutorial #14 - Deploying to Vercel