How To Set Up Mongoose With Typescript In NextJS ?
Last Updated :
09 Jun, 2025
Combining Mongoose with TypeScript in a Next.js project is an intelligent approach to develop scalable, type-safe, and maintainable full-stack web applications. Mongoose offers a powerful ODM (Object Data Modeling) layer to interact with MongoDB, and TypeScript provides static typing to detect issues early and enhance developers productivity. The article will demonstrate the setup process for Mongoose with TypeScript in a Next.js project so your application is resilient, scalable, and maintainable.
Why Use Mongoose with TypeScript in Next.js?
- Strong typing: TypeScript ensures your MongoDB schemas and queries are type-safe, reducing runtime errors.
- Modern full-stack development: Next.js 13 offers server-side rendering and API routes that seamlessly integrate with Mongoose.
- Scalable architecture: MongoDB’s flexible schema plus Mongoose’s schema enforcement fits well with scalable apps.
- Improved developer experience: Autocompletion, better refactoring, and fewer bugs with TypeScript.
Step 1: Create a New Next.js App with TypeScript
Create your Next.js 13 app using the official CLI and navigate to the project folder:
npx create-next-app my-next-app
cd my-next-app
Step 2: Install the required dependencies
Install Mongoose, MongoDB native driver, TailwindCSS (for styling), and React Hook Form (for form handling):
npm install tailwindcss react-hook-form mongoose mongodb
Step 3: Project Structure
Project StructureAdd your MongoDB connection string securely in a .env.local
file at the root of your project:
MONGOB_URI = mongodb+srv://yourMongodbnab:[email protected]/DatabaseName
The Updated dependencies of your package.json file will look like this:
"dependencies": {
"mongoose": "^8.4.0",
"next": "13.4",
"react": "^18",
"react-dom": "^18"
}
Example: Uploading an Image to MongoDB using only NextJS 13.4.
JavaScript
// utils/connectToDb.ts
import mongoose, { Connection } from "mongoose";
import { GridFSBucket } from "mongodb";
let client: Connection | null = null;
let bucket: GridFSBucket | null = null;
const MONGODB_URI = process.env.MONGODB_URI as string;
interface DbConnection {
client: Connection;
bucket: GridFSBucket;
}
async function connectToDb(): Promise<DbConnection> {
if (client) {
return { client, bucket: bucket as GridFSBucket };
}
await mongoose.connect(MONGODB_URI);
client = mongoose.connection;
bucket = new mongoose.mongo.GridFSBucket(client.db, {
bucketName: "images",
});
console.log("Connected to the Database");
return { client, bucket };
}
export default connectToDb;
JavaScript
// utils/posts.ts
import mongoose, { Schema, Document, Model } from "mongoose";
interface IPost extends Document {
name: string;
imageUrl: string;
}
const postsSchema: Schema<IPost> = new Schema({
name: { type: String, required: true },
imageUrl: { type: String, required: true },
});
const PostModel: Model<IPost> = mongoose.models.Posts || mongoose.model<IPost>("Posts", postsSchema);
export default PostModel;
JavaScript
// api/route.tsx
import { NextResponse } from "next/server";
import { Readable } from "stream";
import Posts from "../../utils/posts";
import connectToDb from "../../utils/connectToDb";
export const revalidate = 0;
export const POST = async (req: Request) => {
const { client, bucket } = await connectToDb();
let name: string | undefined;
let image: string | undefined;
const formData = await req.formData();
console.log(formData);
for (const entries of Array.from(formData.entries())) {
const [key, value] = entries;
if (key === "name") {
name = value as string;
}
if (typeof value === "object" && value instanceof File) {
image = Date.now() + value.name;
console.log("done");
const buffer = Buffer.from(await value.arrayBuffer());
const stream = Readable.from(buffer);
const uploadStream = bucket.openUploadStream(image, {});
stream.pipe(uploadStream);
await new Promise((resolve, reject) => {
uploadStream.on('finish', resolve);
uploadStream.on('error', reject);
});
}
}
if (name && image) {
const newItem = new Posts({
name,
imageUrl: image,
});
await newItem.save();
} else {
return NextResponse.json(
{ msg: "Invalid form data" },
{ status: 400 }
);
}
return NextResponse.json({ msg: "ok" });
};
export const GET = async () => {
await connectToDb();
const posts = await Posts.find({});
return NextResponse.json(posts);
};
JavaScript
// components/newPost.tsx
"use client";
import Image from "next/image";
import { useRouter } from "next/navigation";
import { useState, ChangeEvent } from "react";
import {
useForm,
SubmitHandler,
} from "react-hook-form";
interface FormData {
name: string;
imageUrl: FileList;
}
const NewPost = () => {
const { register, handleSubmit, reset } =
useForm<FormData>();
const [previewImage, setPreviewImage] =
useState<string | null>(null);
const router = useRouter();
const handleFileChange = (
e: ChangeEvent<HTMLInputElement>
) => {
const file = e.target.files
? e.target.files[0]
: null;
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setPreviewImage(
reader.result as string
);
};
reader.readAsDataURL(file);
} else {
setPreviewImage(null);
}
};
const onSubmit: SubmitHandler<
FormData
> = async (data) => {
const formData = new FormData();
formData.append("name", data.name);
if (data.imageUrl) {
for (
let i = 0;
i < data.imageUrl.length;
i++
) {
formData.append(
"imageUrl",
data.imageUrl[i]
);
}
}
await fetch("/api", {
method: "POST",
body: formData,
});
// Clear form data and reset input fields
setPreviewImage(null);
reset();
router.refresh();
};
return (
<main className="flex flex-col items-center
justify-between ">
<div className="max-w-md mx-auto">
<form
className="bg-white shadow-md
rounded px-8 pt-6 pb-8 mb-4"
onSubmit={handleSubmit(
onSubmit
)}
>
<div className="mb-4">
<label
className="block text-gray-700
text-sm font-bold mb-2"
htmlFor="input1"
>
Text Input 1
</label>
<input
className="shadow appearance-none
border rounded w-full py-2 px-3
text-gray-700 leading-tight
focus:outline-none focus:shadow-outline"
id="input1"
type="text"
placeholder="Enter text input 1"
{...register("name")}
/>
</div>
<div className="mb-4">
<label
className="block text-gray-700
text-sm font-bold mb-2"
htmlFor="fileInput"
>
File Input
</label>
<input
type="file"
accept="image/*"
className="file-input
file-input-bordered w-full max-w-xs"
id="fileInput"
{...register(
"imageUrl"
)}
onChange={
handleFileChange
}
/>
{previewImage && (
<Image
width={200}
height={200}
src={previewImage}
alt="Preview"
className="mt-2 w-full h-32 object-cover"
/>
)}
</div>
<div className="flex items-center justify-between">
<button
className="bg-blue-500 hover:bg-blue-700
text-white font-bold py-2 px-4
rounded focus:outline-none focus:shadow-outline"
type="submit"
>
Submit
</button>
</div>
</form>
</div>
</main>
);
};
export default NewPost;
JavaScript
//page.tsx
import NewPost from "./components/newPost";
import React from "react";
const Home: React.FC = () => {
return (
<div className="">
<div className="my-20">
<NewPost />
</div>
</div>
);
};
export default Home;
Step 5: Run Your Next.js Development Server
Start your Next.js app locally:
npm run dev
Open your browser and visit:
http://localhost:3000
Output:
OutputWhen you enter the file name, upload a file, and then click on the submit button, your file is successfully uploaded to MongoDB.
Conclusion
Configuring Mongoose with TypeScript within Next.js enables you to develop strong, type-safe, and scalable full-stack applications. With the configuration, you enjoy MongoDB's versatility, Mongoose's schema validation, and TypeScript's developer productivity. Using GridFS for file storage incorporates significant features to manage large files such as images or videos.
Similar Reads
How to Use NextJS in Typescript? TypeScript enhances Next.js applications by adding static type checking and improves developer experience through type safety. Integrating TypeScript into your Next.js project helps catch errors early and improves code maintainability. It offers even greater productivity and robustness to your web d
5 min read
How to add TypeScript in Next.js ? In this article, we will learn how to add TypeScript in Next.js.Why should we use TypeScript in our project? The fundamental concept of TypeScript is that it is type-strict, which means that each entity, be it a variable, a function, or an object has a definite data type. It allows minimum bugs in t
5 min read
How to update record without objectID in mongoose? Mongoose is an ODM(Object Data Library) for MongoDB in Node JS that helps to write schema, validation and business logic in a simple way without the hassle of native MongoDB boilerplate. PrerequisitesUnderstanding of Mongoose and MongoDBData Modeling and Schema DesignMongoose Query MethodsApproach t
3 min read
How to use Typescript with native ES6 Promises ? What is TypeScript? TypeScript is a free as well as an open-source programming language which was developed and is maintained by Microsoft. It actually provides highly productive development tools for JavaScript IDEs and also for practices like static checking. It even makes code easier to read and
3 min read
How to Setup a TypeScript Project? In the world of modern web development, TypeScript has emerged as a powerful superset of JavaScript, offering static typing and improved tooling. Its strong typing system helps developers catch errors early during development, leading to more maintainable and scalable code. Whether you're starting a
2 min read
How to use TypeScript to build Node.js API with Express ? TypeScript is a powerful version of JavaScript that incorporates static typing and other features, making it easy to build and maintain large applications. Combined with Node.js and Express, TypeScript can enhance your development experience by providing better type safety and tools. This guide will
4 min read
How to Make Next.js getStaticProps Work With Typescript? Next.js is a popular React framework that developers use to create efficient server-rendered and static applications. One of the key features is to fetch data at build time, using a function called getStaticProps. This function enables developers to make static pages that are served fast to users, t
5 min read
How to Use MongoDB and Mongoose with Node.js ? MongoDB is a popular NoSQL database that offers flexibility and scalability, making it an excellent choice for modern applications. Mongoose, a powerful ODM (Object Data Modeling) library, simplifies the interaction between MongoDB and Node.js by providing a schema-based solution for data validation
6 min read
Using Mongoose with NestJS NestJS is a progressive Node.js framework for building efficient, reliable, and scalable server-side applications. It provides a solid foundation for backend development with TypeScript support, built-in decorators, and a modular architecture. Mongoose, on the other hand, is a powerful Object Data M
3 min read
How to set the document value type in MongoDB using Node.js? Mongoose.module is one of the most powerful external module of the node.js. Mongoose is a MongoDB ODM i.e (Object database Modelling) that used to translate the code and its representation from MongoDB to the Node.js server. Mongoose module provides several functions in order to manipulate the docum
2 min read