Tech Stack:
Frontend: Next.js
- Backend: Node.js + Express.js
- Database: PostgreSQL
- ORM: Sequelize
- Interview technical round project Flow
Create Frontend
npx create-next-app@latest frontend
touch .envCreate Backend & Install Backend Dependencies
mkdir backend
cd backend
npm init -y
npm install express cors dotenv bcryptjs jsonwebtoken pg pg-hstore sequelize
npm install -D nodemon sequelize-cliBackend Folder Structure Commands
mkdir config controllers middleware models routes migrations seeders
touch server.js
touch config/db.js
touch middleware/authMiddleware.js
touch controllers/authController.js
touch controllers/*.js
touch controllers/*.js
touch routes/authRoutes.js
touch routes/*.js
touch routes/*.js
touch .env
Frontend Dependencies
cd frontend
npm install axios react-hot-toast
touch .env
If want to setup Tailwind go to tailwind site and chose v3 and do the setup.package.json Scripts
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
}Sequelize Initialization & PostgreSQL Database Creation
npx sequelize-cli init
This creates:
config/
models/
migrations/
seeders/
Open PostgreSQL terminal:
CREATE DATABASE employee_management;Backend & Frontend .env File
Backend:
PORT=5000
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=yourpassword
DB_NAME=employee_management
JWT_SECRET=mysecretkey
Frontend:
NEXT_PUBLIC_BASE_URL=http://localhost:5000
Sequelize Config for PostgreSQL
config/config.json
{
"development": {
"username": "postgres",
"password": "",
"database": "",
"host": "localhost",
"dialect": "postgres"
}
}
- Database Connection config/db.js
const { Sequelize } = require("sequelize");
require("dotenv").config();
const sequelize = new Sequelize(
process.env.DB_NAME,
process.env.DB_USER,
process.env.DB_PASSWORD,
{
host: process.env.DB_HOST,
port: process.env.DB_PORT,
dialect: "postgres",
logging: false,
}
);
module.exports = sequelize;
Generate Models and Migrations & Run Migration
User Model
npx sequelize-cli model:generate --name User --attributes name:string,email:string,password:string
Run Migration
npx sequelize-cli db:migrateExpress Server Setup
server.js
const express = require("express");
const cors = require("cors");
require("dotenv").config();
const app = express();
app.use(cors());
app.use(express.json());
app.use("/api/auth", require("./routes/authRoutes"));
app.use("/api/employees", require("./routes/employeeRoutes"));
app.use("/api/attendance", require("./routes/attendanceRoutes"));
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`Server running on ${PORT}`);
});
- Authentication Middleware middleware/authMiddleware.js
const jwt = require("jsonwebtoken");
module.exports = (req, res, next) => {
try {
const token = req.headers.authorization?.split(" ")[1];
if (!token) {
return res.status(401).json({
message: "No token provided",
});
}
const decoded = jwt.verify(
token,
process.env.JWT_SECRET
);
req.user = decoded;
next();
} catch (error) {
res.status(401).json({
message: "Invalid token",
});
}
};
- Login Controller controllers/authController.js
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const { User } = require("../models");
exports.login = async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({
where: { email },
});
if (!user) {
return res.status(400).json({
message: "User not found",
});
}
const isMatch = await bcrypt.compare(
password,
user.password
);
if (!isMatch) {
return res.status(400).json({
message: "Invalid credentials",
});
}
const token = jwt.sign(
{ id: user.id },
process.env.JWT_SECRET,
{
expiresIn: "1d",
}
);
res.json({
token,
user,
});
} catch (error) {
res.status(500).json({
message: error.message,
});
}
};
- Auth Routes routes/authRoutes.js
const router = require("express").Router();
const controller = require("../controllers/authController");
router.post("/login", controller.login);
module.exports = router;
12. Axios Setup
src/utils/axios.js
import axios from "axios";
const api = axios.create({
baseURL: process.env.NEXT_PUBLIC_BASE_URL,
});
api.interceptors.request.use((config) => {
const token = localStorage.getItem("token");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
export default api;
- React Router Setup src/app/App.js
import {
createBrowserRouter,
Navigate,
RouterProvider
} from "react-router-dom";
import React from "react";
import ReactDOM from "react-dom/client";
import Login from "./pages/Login";
import Register from "./pages/Register";
import Home from "./pages/Home";
import Profile from "./pages/Profile";
function PrivateRoute({ children }) {
const isLoggedIn = localStorage.getItem("token");
return isLoggedIn
? children
: <Navigate to="/login" />;
}
function PublicRoute({ children }) {
const isLoggedIn = localStorage.getItem("token");
return isLoggedIn
? <Navigate to="/" />
: children;
}
const router = createBrowserRouter([
{
path: "/login",
element: (
<PublicRoute>
<Login />
</PublicRoute>
),
},
{
path: "/register",
element: (
<PublicRoute>
<Register />
</PublicRoute>
),
},
{
path: "/",
element: (
<PrivateRoute>
<Home />
</PrivateRoute>
),
},
{
path: "/profile",
element: (
<PrivateRoute>
<Profile />
</PrivateRoute>
),
},
]);
function App() {
return (
<div>
<RouterProvider router={router} />
</div>
);
}
export default App;
- Login API Example src/app/login/login.js
import api from "@/utils/axios";
import { useRouter } from "next/navigation";
const router = useRouter();
const login = async () => {
const res = await api.post("/auth/login", {
email,
password,
});
localStorage.setItem(
"token",
res.data.token
);
router.push("/");
};
- Logout Function
import { useRouter } from "next/navigation";
const router = useRouter();
const logout = () => {
localStorage.removeItem("token");
router.push("/login");
};
EXAMPLES
- Next.js Routing src/app/login/page.js
src/app/dashboard/page.js
src/app/employees/page.js
- Redirect After Login import { useRouter } from "next/navigation";
const router = useRouter();
router.push("/dashboard");
- Important PostgreSQL Commands Open PostgreSQL psql -U postgres
Show Databases
\l
Connect Database
\c employee_management
Show Tables
\dt
- Migration Commands Run Migration npx sequelize-cli db:migrate
Undo Last Migration
npx sequelize-cli db:migrate:undo
Undo All Migration
npx sequelize-cli db:migrate:undo:all
- Raw Query Example const sequelize = require("../config/db");
const [employees] = await sequelize.query(
'SELECT * FROM "Employees"'
);
console.log(employees);
- Sequelize Query Examples Create await Employee.create({ name: "Parth", email: "parth@gmail.com", });
Find All
await Employee.findAll();
Find One
await Employee.findOne({
where: {
id: 1,
},
});
Update
await Employee.update(
{
name: "Updated",
},
{
where: {
id: 1,
},
}
);
Delete
await Employee.destroy({
where: {
id: 1,
},
});
- Example Migration File migrations/XXXXXXXXXXXX-create-user.js "use strict";
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable("Users", {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER,
},
name: {
type: Sequelize.STRING,
},
email: {
type: Sequelize.STRING,
unique: true,
},
password: {
type: Sequelize.STRING,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
});
},
async down(queryInterface, Sequelize) {
await queryInterface.dropTable("Users");
},
};
- Example Model File models/user.js "use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
class User extends Model {
static associate(models) {}
}
User.init(
{
name: DataTypes.STRING,
email: DataTypes.STRING,
password: DataTypes.STRING,
},
{
sequelize,
modelName: "User",
}
);
return User;
};
- Importing Models Usage const db = require("../models"); const { User, Employee, Attendance } = db;
Tailwind setup Core React
Install Tailwind CSS v3
npm install -D tailwindcss@3Create Tailwind Config File
npx tailwindcss init
This creates:
tailwind.config.jsConfigure Template Paths
Inside tailwind.config.js
/** @type {import('tailwindcss').Config} /
export default {
content: ["./src//.{html,js,jsx}"],
theme: {
extend: {},
},
plugins: [],
}Add into index CSS File
Create:
src/index.css
Add:
@tailwind base;
@tailwind components;
@tailwind utilities;Start Tailwind Build Process
Run:
npx tailwindcss -i ./src/input.css -o ./src/output.css --watch
This command:
Reads Tailwind classes from input.css
Generates final CSS into output.css
Watches for live changes
Top comments (0)