We are going to create a Next.js application that uses both client-side and server-side rendering with authentication and data fetching. We'll implement the following features:
- Authentication: A simple login flow using a mock API.
- Data Fetching: Display user-specific data fetched from a backend.
Add a Database
we'll use SQLite with Prisma (an ORM).Install Prisma:
npm install prisma --save-dev
npm install @prisma/client
Initialize Prisma:
npx prisma init
- Update the prisma/schema.prisma file to define a User model:
datasource db {
provider = "sqlite"
url = "file:./dev.db"
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int @id @default(autoincrement())
email String @unique
password String
}
- Migrate the database:
npx prisma migrate dev --name init
- npx prisma migrate dev --name init
npx prisma migrate dev --name init
npx prisma db seed
Next, we will add Login API (pages/api/auth/login.js):
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ message: 'Method not allowed' });
}
const { email, password } = req.body;
try {
const user = await prisma.user.findUnique({ where: { email } });
if (!user || !bcrypt.compareSync(password, user.password)) {
return res.status(401).json({ message: 'Invalid credentials' });
}
const token = jwt.sign({ email: user.email, id: user.id }, process.env.JWT_SECRET, { expiresIn: '1h' });
res.status(200).json({ token });
} catch (error) {
res.status(500).json({ message: 'Internal server error' });
}
}
Create User API (pages/api/auth/register.js): Add an API route to register new users.
import bcrypt from 'bcryptjs';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ message: 'Method not allowed' });
}
const { email, password } = req.body;
try {
const hashedPassword = bcrypt.hashSync(password, 10);
const newUser = await prisma.user.create({
data: { email, password: hashedPassword },
});
res.status(201).json({ message: 'User created', user: newUser });
} catch (error) {
res.status(500).json({ message: 'Internal server error' });
}
}
Update Data Fetching API
Modify the pages/api/user.js route to fetch user data from the database.
import jwt from 'jsonwebtoken';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export default async function handler(req, res) {
const { authorization } = req.headers;
if (!authorization) {
return res.status(401).json({ message: 'Unauthorized' });
}
try {
const token = authorization.split(' ')[1];
const decoded = jwt.verify(token, process.env.JWT_SECRET);
const user = await prisma.user.findUnique({ where: { id: decoded.id } });
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
res.status(200).json({ email: user.email, message: 'Welcome to your dashboard!' });
} catch (error) {
res.status(401).json({ message: 'Invalid token' });
}
}
Environment Setup
In .env.local, configure the database connection:
DATABASE_URL="file:./dev.db"
JWT_SECRET="your-secret-key"
Test the Application
npm run dev
After the application gets started:
Use Postman or the frontend to:
- Register a new user: Use the /api/auth/register endpoint.
- Log in: Use the /api/auth/login endpoint.
- Fetch user data: Use the /api/user endpoint with a valid token.
Top comments (0)