STAY INFORMED
following content serves as a personal note and may lack complete accuracy or
certainty.
Minimal-Mistakes instruction
Useful vscode Shortcut Keys
Unix Commands
npm Commands
Vim Commands
Git Note
Useful Figma Shortcut Keys
Deploy Unity Project With WebGL
Auth
I created auth directory and created login, signup, logout pages and api routes.
To store user’s data, I used MySQL with Prisma.
npm install prisma @prisma/client
npx prisma init
Changed prisma file
// prisma/schema.prisma
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
// Define User
model User {
id Int @id @default(autoincrement())
email String @unique
password String
nickname String
}
and migrated
npx prisma migrate dev --name init
# after --name is like comment(optional)
If you have changed prisma file you have to migrate again and generate prisma client
npx prisma generate
and install bcyrpt for hashing password
npm install bcrypt
Sign Up
In Next.js, if you use App Router and you want to use react components, you need this line. I added it at very top.
"use client";
Client Side
Implemented InputField
const InputField = ({ label, type, value, onChange, error400, error409 }) => {
return (
<>
<div className="m-5">
<label>{label}</label>
<input
className="text-blue-500"
type={type}
value={value}
onChange={onChange}
/>
<span className={`text-red-500 ${error400 ? "" : "hidden"}`}>
{error400}
</span>
<span className={`text-red-500 ${error400 ? "" : "hidden"}`}>
{error409}
</span>
</div>
</>
);
};
useState
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [nickname, setNickname] = useState("");
const [error400, setError400] = useState([]);
const [error409, setError409] = useState([]);
form submit function
const handleSubmit = async (e) => {
e.preventDefault();
setErrors([]); // reset errors
const res = await fetch("/api/auth/signup", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email, password, nickname }),
});
const data = await res.json(); // get data from api
if (res.ok) {
console.log(`success ${JSON.stringify(data)}`);
} else {
// check 400 error first
if (res.status === 400) {
setError400(data.errors);
}
// then check 409 error
else if (res.status === 409) {
setError409(data.errors);
}
}
};
Server Side
Import what I need and initialize prisma client.
import { NextResponse } from "next/server";
import { PrismaClient } from "@prisma/client";
import bcrypt from "bcrypt";
const prisma = new PrismaClient();
I distinguish 400, 409 errors.
if 400 error that at least one required field is empty, return that first and next check 409 error that there is a duplicated email or nickname.
const body = await req.json();
const { email, nickname, password, confirmPassword } = body;
const error400 = [];
const error409 = [];
try {
if (!email) {
error400.push("email");
}
if (!nickname) {
error400.push("nickname");
}
if (!password) {
error400.push("password");
} else if (password != confirmPassword) {
error400.push("confirmPassword");
}
// if at least one required field is empty, return bad request
if (error400.length > 0) {
return NextResponse.json({ errors: error400 }, { status: 400 });
}
const existingUser = await prisma.user.findMany({
where: {
OR: [{ email }, { nickname }],
},
});
if (existingUser.length > 0) {
existingUser.forEach((user) => {
if (user.email === email) {
error409.push("email");
}
if (user.nickname === nickname) {
error409.push("nickname");
}
});
}
// if there is at least one error, return conflict
if (error409.length > 0) {
return NextResponse.json({ errors: error409 }, { status: 409 });
}
If all good, return 201
// hash password
const hashedPassword = await bcrypt.hash(password, 10);
// create user
const user = await prisma.user.create({
data: {
email,
password: hashedPassword,
nickname,
},
});
// return created request
return NextResponse.json({ message: "success", user }, { status: 201 });
and disconnect prisma to prevent memory leak.
finally {
// to prevent memory leak
await prisma.$disconnect();
}