
Connect to MongoDB from the Next.js App Router Project
5 min read
By Avinash
Install the MongoDB Node.js Driver
npm install mongoose
[!NOTE] You should have set up the MongoDB Atlas cluster and have the connection string ready. Add the Shadcn UI dependencies to the project.
npm install @shadcn/ui
Add the below components to the project.
npx shadcn@latest add button
npx shadcn@latest add input
npx shadcn@latest add label
npx shadcn@latest add card
npx shadcn@latest add form
npx shadcn@latest add checkbox
npx shadcn@latest add toast
Add the below dependencies to the project.
npm install lucide-react
npm install sonner
Creating the environment variable in the .env.local file
MONGODB_URI=your_mongodb_connection_string
Creating the connection to the MongoDB database using the mongoose library
Create a new file lib/mongoose.js and add the below code to it.
import mongoose from 'mongoose';
const MONGODB_URI = process.env.MONGODB_URI;
if (!MONGODB_URI) {
throw new Error('Please define the MONGODB_URI environment variable inside .env.local');
}
let cached = global.mongoose;
if (!cached) {
cached = global.mongoose = { conn: null, promise: null };
}
async function connectDB() {
if (cached.conn) {
return cached.conn;
}
if (!cached.promise) {
const opts = {
bufferCommands: false,
};
cached.promise = mongoose.connect(MONGODB_URI, opts).then((mongoose) => {
return mongoose;
});
}
try {
cached.conn = await cached.promise;
} catch (e) {
cached.promise = null;
throw e;
}
return cached.conn;
}
export default connectDB;
Create the Todo model
Create a new file models/Todo.js and add the below code to it.
import mongoose from 'mongoose';
const todoSchema = new mongoose.Schema({
text: {
type: String,
required: [true, 'Todo text is required'],
trim: true,
},
completed: {
type: Boolean,
default: false,
},
createdAt: {
type: Date,
default: Date.now,
},
updatedAt: {
type: Date,
default: Date.now,
}
}, {
timestamps: true
});
// Prevent mongoose from creating a plural collection name
const Todo = mongoose.models.Todo || mongoose.model('Todo', todoSchema);
export default Todo;
Using the connection in the project and create the API routes
Let create a backend API route to test the connection to the MongoDB database.
Create a new file app/api/todos/route.js and add the below code to it.
import { NextResponse } from 'next/server';
import connectDB from '@/lib/mongoose';
import Todo from '@/models/Todo';
export async function GET() {
try {
console.log('Connecting to database...');
await connectDB();
console.log('Database connected successfully');
console.log('Fetching todos from database...');
const todos = await Todo.find({}).sort({ createdAt: -1 });
console.log('Todos fetched successfully:', todos);
return NextResponse.json(todos);
} catch (error) {
console.error('Error in GET /api/todos:', error);
console.error('Error details:', {
message: error.message,
stack: error.stack,
name: error.name
});
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
export async function POST(request) {
try {
console.log('Connecting to database...');
await connectDB();
console.log('Database connected successfully');
const body = await request.json();
console.log('Received todo data:', body);
console.log('Creating new todo...');
const todo = await Todo.create({
text: body.text,
completed: false,
});
console.log('Todo created successfully:', todo);
return NextResponse.json(todo, { status: 201 });
} catch (error) {
console.error('Error in POST /api/todos:', error);
console.error('Error details:', {
message: error.message,
stack: error.stack,
name: error.name
});
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
export async function PUT(request) {
try {
console.log('Connecting to database...');
await connectDB();
console.log('Database connected successfully');
const body = await request.json();
console.log('Received update data:', body);
console.log('Updating todo...');
const todo = await Todo.findByIdAndUpdate(
body._id,
{
text: body.text,
completed: body.completed,
},
{ new: true, runValidators: true }
);
if (!todo) {
console.error('Todo not found with id:', body._id);
return NextResponse.json({ error: 'Todo not found' }, { status: 404 });
}
console.log('Todo updated successfully:', todo);
return NextResponse.json(todo);
} catch (error) {
console.error('Error in PUT /api/todos:', error);
console.error('Error details:', {
message: error.message,
stack: error.stack,
name: error.name
});
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
export async function DELETE(request) {
try {
console.log('Connecting to database...');
await connectDB();
console.log('Database connected successfully');
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
console.log('Deleting todo with id:', id);
const todo = await Todo.findByIdAndDelete(id);
if (!todo) {
console.error('Todo not found with id:', id);
return NextResponse.json({ error: 'Todo not found' }, { status: 404 });
}
console.log('Todo deleted successfully:', todo);
return NextResponse.json({ message: 'Todo deleted successfully' });
} catch (error) {
console.error('Error in DELETE /api/todos:', error);
console.error('Error details:', {
message: error.message,
stack: error.stack,
name: error.name
});
return NextResponse.json({ error: error.message }, { status: 500 });
}
}
Observe the style of the code.
- The code is modular and follows the SOLID principles.
- Usage of try catch blocks to handle errors.
- Usage of
console.logto debug the code.- Usage of
NextResponseto return the response. We can test the API routes using thecurlcommand or using the Postman tool.
Let's test the API routes using the curl command.
curl -X GET http://localhost:3000/api/todos
This ends the tutorial on how to connect to MongoDB from the Next.js App Router Project and create a backend API route to test the connection to the MongoDB database.