DEV Community

Cover image for Build your own CMS using low-code
Shubhendra Singh Chauhan for ToolJet

Posted on • Originally published at blog.tooljet.com

Build your own CMS using low-code

In this tutorial, We will build CMS(Content Management System) using the ToolJet which is a lowcode application development platform. The CMS can be used to perform CRUD operations to the MongoDB which is used as the database for the NextJS application.

Table of Contents


Overview

A content management system (CMS) is an application used for managing content creation and modification, usually articles and blog posts containing images and videos. WordPress CMS is one of the popular CMS. CMSs make it easy to perform CRUD operations (create, read, update, and delete) without coding knowledge.
ToolJet is a free and open-source low-code app development platform that allows you to build applications quickly and has more than 30+ datasources including MongoDB that will let you seamlessly perform operations on your database. You can create a free account on ToolJet Cloud or run it on your local machine.
Many developers use databases like MongoDB and frameworks like NextJS for their full-stack web applications. Sometimes performing CRUD operations can be time taking for developers and can be hectic for someone who is not familiar with running database queries. In this tutorial, we will build an app using ToolJet that will solve these problems. The CMS app will be connected to the MongoDB database to perform CRUD operation, and the changes will be reflected on the NextJS application.

appui

Want to use the app without going through the complete tutorial?

  • Import the exported application JSON file to your ToolJet account. Here's the file.
  • Once imported the application, you'll need to connect the MongoDB datasource using host details or connection string.

Prerequisites

  1. MongoDB database: You can set up the MongoDB database locally or use Atlas. For this tutorial, we are going to use Atlas.
  2. ToolJet (https://github.com/ToolJet/ToolJet): A free and open-source low-code platform that allows you to build applications quickly. Sign up here.
  3. NextJS app: We will learn how to build one sample app using the command line later in this tutorial.

Setting up the database

Once you have created an account on MongoDB Atlas, you'll be asked to enter the username and password for your database (not the same as what you use to log into the MongoDB cloud). Once done, you'll be redirected to your project's database deployment, where you can create/manage Clusters. You can create a new Cluster and choose a configuration according to your preference.

mongo1

As you can see in the screenshot above, we have Cluster0 deployed. Go to the browse collections and create a new database cms with three collections posts, authors, and tags.

  • posts- this collection will store all the blog posts information
  • authors- this collection will store information on all the authors
  • tags - this collection will store the tags

Let's insert at least one sample document in each collection. For posts:

  • _id: the object id will be generated by MongoDB automatically.
  • title: enter the title of the blog posts.
  • subtitle: enter the subtitle
  • content: enter the content/body of blog posts
  • cover: enter the URL of the cover image
  • author_name: enter the name of the author
  • tag_name: enter the tag name
  • published_on: enter the date in DD/MM/YYYY format The data type of all the records should be string.

object

Similarly, we will insert documents in authors and tags. For authors

  • _id: the object id will be generated by MongoDB automatically.
  • author_name: name of the author
  • author_email: email of the author
  • author_image: URL of author's headshot image

authors

For tags:

  • _id: the object id will be generated by MongoDB automatically.
  • tag_name: name of the tag

Once you have inserted the sample documents in all three collections, we are good to go. Our database is ready.

Now, let's go to ToolJet and connect the database.


Connecting MongoDB to ToolJet

Let's go to the ToolJet dashboard and create a new app. Once you click the New App button, an untitled app will open in the app builder. You can rename the app from the toolbar. On the left sidebar, you'll find the third option for adding or editing datasources.

newapp

Click on the + add datasource and a modal will pop up with a list of all the available datasources. Select MongoDB from the list and enter the credentials for connecting.

datasource

For this tutorial, we are using MongoDB Atlas to connect to MongoDB datasource using the connection string.

creds

You can find your connection string by going to the MongoDB Atlas dashboard. Go to Database Deployments on the Atlas and click on the Connect button next to the cluster name ( Cluster0 in our case). A connection dialog will pop up to choose the method by which you want to connect, click on the second option - Connect your application. Once you click on the second option, you'll get the connection string - click on the copy button next to it to copy the string.

mongodash

The string that you'll copy will be like this mongodb+srv://testusername:<password>@cluster0.nc8nial.mongodb.net/?retryWrites=true&w=majority where testusername is the database username that we created before, we will need to replace <password> with the password that we created for this database and then remove everything after .net/ and add your database name - in our case, the name of the database is cms.

So, the actual connection string will be: mongodb+srv://testusername:fakepassword@cluster0.nc8nial.mongodb.net/cms

Copy-paste the connection string on the ToolJet and click on the test connection button to test the connection before saving the datasource once the connection is successful then save the datasource.

success

Now, that we have successfully connected the MongoDB database, we can build the user interface of the CMS app.


Build the UI of the CMS app

Let's start building the UI of the CMS application using ToolJet, which is a low-code application development platform.

The CMS application is a multi-page application that will have the following 5 pages:

All Posts

allpostsimage

New Post

newpostimage

Edit Post

editpost

View Post

viewpost

Authors and Tags

allpostsimage

In the previous section, we connected the MongoDB datasource to a new application. Now, all we need to do is build the UI and then create queries and connect them with the UI.

The very first thing we are going to do is create Pages in our application. We can find the Pages option on the left sidebar from where we can add the pages to the application. Let's add the following pages:

  • all_posts
  • new_post
  • edit_post
  • view_post
  • authors_tags

pages

๐Ÿ’ก Before we begin with UI, it is recommended to learn about ToolJet's app builder: https://docs.tooljet.com/docs/app-builder/overview

All Posts: UI

The All Posts page will show the list of all the blog posts. This is going to be the home page of the application, and from this page, we can navigate to other pages.

This page will use the listview component to show a list of blogs and buttons to navigate other pages. Let's build the UI:

  • Let's drag a container on the canvas and increase its height to reach the bottom and its width to both sides. You can click on the handle of the container to edit its properties.
  • Drag a text component and set its value to <h1>All Posts</h1>. Yes, we can use HTML tags inside the text component to format text value.
  • Drag a divider below the text component.

all_post_ui

  • Now drag two button components above the right side of the divider and style the buttons.
  • For the first button, we will set the button text to New Post and edit its Styles. Set the button color to #14171a , text color to white/#ffffff, loader color to white, border-radius to 2 , border color to #14171a
  • Add an Event Handler to the New Post button, choose switch page action, and then select the new_post from the dropdown. Now, whenever the button is clicked New Post page of the application will be loaded.

allpostui

  • For the second button, we will set the button text to Authors and Tags and edit its Styles. Set the button color to white/#ffffff , text color to #14171a, loader color to #14171a, border-radius to 2 , border color to #14171a
  • Add an Event Handler to the Authors & Tags button, choose switch page action, and select the authors_tags from the dropdown. Now, whenever the button is clicked Authors & Tags page of the application will be loaded.

authortagss

  • Now drag a listview component below the divider. Go to its Styles and set the border color to white.

listview1

  • Let's add components inside the listview. Remove the image component, and add three text components and two buttons as shown in the image below.

listview2

  • Currently, the listview looks very rough since we haven't styled the nested components (text and buttons) yet. To make it look better, we can add some styling to the components and some placeholder text until we create the query for the data to be loaded into the listview.
  • Let's edit the properties and styles of the nested text components and buttons:
    • text1: Text = Title of the blog , Font weight = Bold , Font size = 16
    • text2: Text = By Author - 06/02/2023 , Font weight = Lighter
    • text3: Text = Tag , Font weight = Lighter
    • button1: Button text = ๐Ÿ‘๏ธ , Background color = white , Border radius = 2 , Border color = #e2e4e4
    • button2: Button text = โœ๏ธ , Background color = white , Border radius = 2 , Border color = #e2e4e4

listview3

  • For the view/๐Ÿ‘๏ธ and edit/โœ๏ธ buttons inside listview, we need to add event handlers. On both buttons, we need to add an event handler for set variable event that creates a variable selectedListViewIndex and the variable value will be {{listItem._id}} - this value will be there once we create the query. Another event handler that we need to add is to switch the page, for the edit button link edit_post page and for the view button link view_post page.

listview4

The UI of the All Posts page is almost finished, now let's go ahead and build the queries and connect to the UI.

All Posts: Queries

Let's build the required query for loading the data on All Posts page. Since we are only loading the list of all the blogs from the database on the listview, we need to build a single query:

posts

  • Go to the query panel at the bottom of the app builder, create a new MongoDB query, and name it as posts
  • Select the Find Many Operation from the dropdown options and then enter the Collection name as posts which is the name of the collection in our cms db that we created in MongoDB Atlas
  • From the Advanced section, toggle on the Run query on application load? option, and then save the query. This will execute the query every time the app is loaded.
  • Run the query to trigger it, and we can check the data returned by the query from the inspector panel on the left sidebar.

postsquery

authors

  • Create a new MongoDB query, and name it as authors
  • Select the Find Many Operation from the dropdown options and then enter the Collection name as authors which is the name of the collection in our cms db that we created in MongoDB Atlas
  • From the Advanced section, toggle on the Run query on application load? option, and then save the query. This will execute the query every time the app is loaded.
  • Run the query to trigger it and we can check the data returned by the query from the inspector panel on the left sidebar.

authorsquery

tags

  • Create a new MongoDB query, and name it as tags
  • Select the Find Many Operation from the dropdown options and then enter the Collection name as tags which is the name of the collection in our cms db that we created in MongoDB Atlas
  • From the Advanced section, toggle on the Run query on application load? option, and then save the query. This will execute the query every time the app is loaded.
  • Run the query to trigger it and we can check the data returned by the query from the inspector panel on the left sidebar.

tags query

All Posts: Connecting queries data to UI

  • Now, that we have the posts, authors, and tags data from the database, we can populate the listview component. Edit the properties of the ListView component and set the List data value to {{queries.posts.data}}.

connectingui

  • The rows will be added to the listview but the actual data won't show up because the components inside the listview currently hold the placeholder values. Let's remove the placeholder values from the components inside the ListView. Go to the text component whose value is Title of the blog and set its value to {{listItem.title}}

uititle

  • Set the value of the second text component to By {{listItem.author_name}} - {{listItem.published_on}}
  • Set the value of the third text component to {{listItem.tag_name}}

uiauthor

We are finally done with the All Posts page, all we need to do now is build the UI of the remaining 4 pages and then connect the queries.


New post: UI

The New Post page will be used to create a new blog post and insert it into the collection posts. Let's click on the New Post button on the top of the All Post page and switch to the new_post page as we have already added the event handler to the button.

This page will use the container component as the body and we will nest components like text, text-input, dropdown, etc. to create a form-like structure for getting the input from the users. Let's build the UI:

  • We are going to build a UI similar to the UI that we build for the All Posts page. First, we will drag a container component onto the canvas and then we will use the text component for the Title of the page i.e New Post with a divider component below it.
  • On the right side of the divider, we can simply copy and paste the Authors & Tags button from the All posts page and paste it into the New Post page. Change the button text to < Back and add the event handler to switch the page to all_posts

dividerui

  • Now we are going to drag components and build a form-like structure below the divider component.
    • We are going to drag a text component, set its value to Title, set Font weight to Bold, and Font Size to 16
    • We will copy-paste(using keyboard shortcuts) the Title text component 5 more times and then change their text to Subtitle, Content, Cover Image, Author, and Tag, respectively.
  • Now, we will place the following components next to the headings:
    • Title: text input component and set placeholder to Title
    • Subtitle: text input component and set placeholder to Subtitle
    • Content: text area component and set placeholder to Content
    • Cover Image: text input component and set placeholder to Cover Image
    • Author: dropdown component and set placeholder to Author
    • Tag: dropdown component and set placeholder to Tag
  • Set the value of the border radius of all the input components to {{2}} to make them look better

formui

  • Our form is almost complete, now at the bottom of the page we will add a button. We will copy-paste the button from the All Posts page and change the button text to Submit. Remove the existing event handlers, and add an event handler to switch the page to all_posts . We will add another event handler once we create the query for submitting the form.

formui2

The UI for creating a new blog post is ready, now let's create the query for inserting the form values into the database.

New post: Queries

add_post

  • Create a new MongoDB query, and name it as add_post
  • Select the Insert One Operation from the dropdown options and then enter the Collection name as posts which is the name of the collection in our cms db that we created in MongoDB Atlas
  • In the Document field, enter the following:
{title: "{{components.textinput1.value}}", subtitle: "{{components.textinput2.value}}", content: "{{components.richtexteditor1.value}}", cover: "{{components.textinput3.value}}", author_name: "{{components.dropdown1.value}}", tag_name: "{{components.dropdown2.value}}", published_on: "{{moment().format("DD/MM/YYYY")}}" }
Enter fullscreen mode Exit fullscreen mode
  • In the code snippet above, we are dynamically getting values from the input components.
  • Go to the bottom of the query manager and add the event handler to run the query on the Query Success event and select the posts query. Doing this will trigger the posts query every time this add_post query is successful or simple words whenever the user submits the blog then the list of the blogs will be refreshed on the front-end. Finally, Save the query.

querymanager

New post: Connecting queries data to UI

On this page, all we need to do is connect the query that we created in the previous step to the submit button so that whenever the button gets clicked, the query for inserting the post is triggered and then the page switches to the home page i.e. All Posts page.

  • Click on the handle of the Submit button, and go to the Events section under its properties.
  • While building the UI we already added an event handler for switching the page to all_posts, now we need to add another event handler to Run the query on the On Click event -> Select the add_post query. Move the Run query event handler above the Switch Page event handler to ensure the query runs first and then the page switches to the home page.

onclickui

Edit post: UI

This page is going to be the clone of the New Post page; we will replace the Submit button with the update button and will add another button for deleting the selected post. Let's go!

  • Let's go to the New Post page and select the container. Press ctrl/cmnd+c, go back to the Edit Post page and press ctrl/cmnd+v, doing this will clone the container entirely including the nested components from the New Post page.
  • Change the Title from New Post to Edit Post
  • Set the default values of the following input components:
    • Default Value for Title's text input : {{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].title}}
    • Default Value for Subtitle's text input : {{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].subtitle}}
    • Default Value for Content's text area : {{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].content}}
    • Default Value for Cover Image's text input: {{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].cover}}
    • Default Value for Author's dropdown component: {{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].author_name}}
    • Option Value for Author's dropdown component: {{queries.authors.data.map(i => i.author_name)}}
    • Option Labels for Author's dropdown component: {{queries.authors.data.map(i => i.author_name)}}
    • Default Value for Tag's dropdown component: {{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].tag_name}}
    • Option Value for Tag's dropdown component: {{queries.tags.data.map(i => i.tag)}}
    • Option Labels for Tag's dropdown component: {{queries.tags.data.map(i => i.tag)}}

editpost

  • Let's go to Submit button and change the button text to Update. We will keep both the event handlers as it is and will replace the query in the Run Query handler later once we build the query.
  • Copy the Back button from the top and paste it below next to the Update button. Change the button text to Delete. We will add the event handler in the next section when we create the query. Go to the Styles, change the button text and border color to red.

backui

The UI of the Edit Post section is finished. We also updated the default values of the components so that whenever a listItem is clicked from the homepage the details of the selected blog details get updated on the edit page field values.

Edit post: queries

delete_post

  • Create a new query from the query panel, and name it delete_post
  • Select the Find one and delete Operation from the dropdown options and then enter the Collection name as posts
  • In the Filter field value enter:
{"title":"{{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].title}}"}
Enter fullscreen mode Exit fullscreen mode
  • Scroll to the bottom, add an event handler to run the query on the Query Success event and select the posts query and then Save the query.

querysucces

update_post

  • Create another MongoDB query from the query panel, and name it update_post
  • Select the Find one and update Operation from the dropdown options and then enter the Collection name as posts
  • In the Filter field value enter:
{"title":"{{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].title}}"}
Enter fullscreen mode Exit fullscreen mode
  • In the Update field value enter:
{ $set: {title:"{{components.textinput1.value}}", subtitle:"{{components.textinput2.value}}", content:"{{components.richtexteditor1.value}}", cover:"{{components.textinput3.value}}", author_name:"{{components.dropdown1.value}}", tag_name:"{{components.dropdown2.value}}"} }
Enter fullscreen mode Exit fullscreen mode

js

  • Scroll to the bottom, add an event handler to run the query on the Query Success event, and select the posts query and then Save the query.

runthequery

Edit post: Connecting queries data to UI

Now, all we need to do is update the event handlers on the Update and Delete buttons.

  • Click on the handle of the Delete button to edit its properties. Go to Events, and change the query in the Run Query event to delete_post

editpostconnnect

  • Similarly, we will update the event handler of the Update button. Open its properties, go to Events, and change the query in the Run Query event to update_post

runqueryui

View post: UI

This page will be loaded when the ๐Ÿ‘๏ธ/view button is clicked next to the item in the listview on the All Posts page. Let's build the UI:

  • Go to the home page/All Posts page and click on the ๐Ÿ‘๏ธ/view post button next to the list item to load the view_post page
  • Once the view_post page is loaded, drag a container component onto the canvas. Expand the container completely both vertically and horizontally to fit the entire canvas.
  • Go to either of the page New Post or Edit Post, copy the back button and paste it on the view_post page. Drag a divider component below the button.
    dragcontainer

  • Now let's drag the following components and set their properties and styles:

    • text component for showing the Title: text = {{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].title}} , font weight = bold, font size = 16
    • text component for showing the Subtitle: text = {{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].subtitle}} , font weight = bold, font size = 15
    • text component for showing the Author: text = Author: {{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].author_name}} , font weight = bold, font size = 14
    • image component for displaying the Cover Image: URL = {{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].cover}}
    • text component for showing Content: text = {{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].content}} , font weight = normal, font size = 14 componentsvalues

View post: Queries

This page doesn't requires any queries. The data on this page is loaded using the queries that we created previously.

View post: Connecting queries data to UI

We have already connected the data while building the UI. We are using variables that we created previously to filter the data according the clicked list item.
For ex: for loading the Title of the selected list view item we have set the value:

{{queries.posts.data.filter(post => post._id == variables.selectedListViewIndex)[0].title}}
Enter fullscreen mode Exit fullscreen mode

Authors & Tags: UI

We are finally at the last page of the application. In this page we are going to display the list of all the author and all the tags. From this page we can perform CRUD operations on authors and tags collection in database. Let's build the UI:

  • Go to the homepage/All Posts page of the application and click on the Authors & Tags button on the page, this will redirect you to the authors_tags page
  • Drag a container onto the canvas and resize(both vertically and horizontally) it to fit the canvas. Copy the back button from any of the other pages and paste it on the top-right of this page
  • Let's add two text components use html tags to make them into Title: Authors, Tags
  • Add two divider components below the titles and two tables respectively. authorsandtagsui
  • Now, we will be adding two buttons, one for adding the authors into the database and the other for adding tags into the database. We can copy the New Post button from the home page to keep the styling same. Remove the event handlers and change the button text to +Add.
    add

  • Drag three modals somewhere below the container. These modals will be shown when the following buttons are clicked: +Add button for Authors, +Add button for tags, and View action button on Authors table.

  • Toggle off the Use default trigger button for all the three modals.
    modalui

  • Go to the properties of +Add button for Authors, add an event handler to show the modal1. Click on the button to show the modal1. Once the modal loads click somewhere outside the modal, then drag the components from the components library onto the modal:

    • 3 text components: Author Name, Author Email, and Author Image
    • 3 text input components : name, email, image URL
    • A button component for triggering the query that we will create in the next section, set the button text to Add

modal1ui

  • Just like the +Add button for Authors, we are going to add an event handler on the +Add button for tags to trigger modal2, open the modal and add the following components inside the modal:
    • 1 text input components: Tag
    • A button component for triggering the queries that we will create in the next section, set the button text to Add Tag

modal2

  • Go to the Authors Table, add two Action buttons: View and Remove. On View action button, we will add an event handler to show the modal3 and the Remove action button will trigger the query that will remove the selected author from the collection.
    modal3

  • Click on the View button to show the modal, add components inside the modal3 just like we have added components in the previous 2 modals:

    • 2 text components: text = {{components.table1.selectedRow.author_name}} & {{components.table1.selectedRow.author_email}}, keep the font weight = bold for the first text component.
    • 1 image component to display the author image: {{components.table1.selectedRow.author_image}}
  • Go to the Tags Table, and add one Action button: Delete. This action button will trigger the query that will remove the selected tag from the collection.

tagstable

Authors & Tags: Queries

add_authors

  • Create a new MongoDB query, name it add_author, select insert one from the operations dropdown, and enter authors in the collection field.
  • In the Document field, enter:
{author_name: "{{components.textinput1.value}}", author_email: "{{components.textinput2.value}}",author_image: "{{components.textinput3.value}}" }
Enter fullscreen mode Exit fullscreen mode
  • Go to the bottom, and add an event handler to run authors query on Query Success Event. Finally, Save the query.

querysuccessevent

add_tags

  • Create a new MongoDB query, name it add_tag, select insert one from the operations dropdown, and enter tags in the collection field.
  • In the Document field, enter:
{tag:"{{components.textinput4.value}}"}
Enter fullscreen mode Exit fullscreen mode
  • Go to the bottom, and add an event handler to run tags query on Query Success Event. Finally, Save the query. savethequery

delete_author

  • Create a new MongoDB query, name it delete_author, select delete one from the operations dropdown, and enter authors in the collection field.
  • In the Filter field, enter:
{"author_name":"{{components.table1.selectedRow.author_name}}"}
Enter fullscreen mode Exit fullscreen mode
  • Go to the bottom, and add an event handler to run authors query on Query Success Event. Finally, Save the query. deleteauthorquery

delete_tag

  • Create a new MongoDB query, name it delete_tag, select delete one from the operations dropdown, and enter tags in the collection field.
  • In the Filter field, enter:
{"tag":"{{components.table2.selectedRow.tag}}"}
Enter fullscreen mode Exit fullscreen mode
  • Go to the bottom, and add an event handler to run authors query on Query Success Event. Finally, Save the query. deletetagquery

Authors & Tags: Connecting queries data to UI

Let's connect the queries to the table components to display the data and the button components for triggering the insert and delete queries:

  • Go to the Author's table, edit its properties, and set table data to {{queries.authors.data}} . The columns will be auto-populated. Enable the highlight selected row from the options and set the loading state of the table to {{queries.delete_author.isLoading || queries.authors.isLoading}}
  • Edit Remove action button and add the event handler to run the delete_author query. This will remove the author from the database whenever the action button is clicked.

connectingauthorstags

  • Click on the +Add Authors button to show the modal, inside modal, there is a Add button for submitting the form. Add the following event handlers to this button:
    • 1st event handler to run the query: add_author
    • the next 3 event handlers to control the component. Components will be the three text inputs that are there in the modal and the Action will be Clear . Adding these event handlers will clear the form as soon as the add_author query is triggered.
    • last event handler for closing the modal.

eventhandlers

  • Now, we are going to add the event handlers to +Add button for the Tags:
    • 1st event handler to run the query: add_tag
    • the next event handler to control the component. Select the text input component that is there in the form and set the Action to Clear .
    • last event handler for closing the modal.

closingthemodal

  • Finally, go to the Tags table, and set the table data to {{queries.tags.data}} . The columns will be auto-populated. Enable the highlight selected row from the options and set the loading state of the table to {{queries.delete_tag.isLoading || queries.tag.isLoading}}
  • Edit delete action button and add the event handler to run the delete_tag query.

loadingstate


Connecting to NextJS app

Using the connection string, we can connect the MongoDB Atlas database to any NextJS app. In this section, we will locally set up a NextJS application and then connect it to the MongoDB database to load the data on the front end.

Requirements:

  • MongoDB Atlas database
  • NodeJS 12+
  • npm and npx
  • Vercel (Optional if you want to deploy your NextJS app)

Building NextJS app

Go to the terminal, and enter the following command:

npx create-next-app --example with-mongodb nextblog
Enter fullscreen mode Exit fullscreen mode

We are using the npx create-next-app command and are passing the --example with-mongodb parameter which will tell create-next-app to bootstrap our app with the MongoDB integration example. Finally, nextblog is the name of our application.

Executing this command will take a couple of seconds to download and install all the npm dependencies, but once they're downloaded and installed, navigate to your project directory by running:

cd nextblog
Enter fullscreen mode Exit fullscreen mode

Install all the npm dependencies by running:

npm install
Enter fullscreen mode Exit fullscreen mode

Now, let's start up our application. To start our Next.js app, execute:

npm run dev
Enter fullscreen mode Exit fullscreen mode

Once the app is built successfully, we can navigate to localhost:3000 to see our app live in action.

localhost1

We will get an error similar to the one in the screenshot above because the app is built but we haven't connected our MongoDB database yet to the application. So let's do that.

Connecting MongoDB

  • On the nextblog directory, we can find the env.local.example file. We can rename the file to env.local and then edit it.
  • In this file, we will need to enter the value for MONGODB_URI and MONGODB_DB variable. MONGODB_URI is nothing but the connection string till / and MONGODB_DB will be the name of the database. Go to the beginning of the tutorial to learn how we can obtain the connection string from the Atlas. The env.local file will look like this:
    envfile

  • As soon as you save these environment variables, go to the browser and you'll see that the error is gone and with-mongodb Next.js app welcome page is loaded.
    welcome

Querying MongoDB with Next.js

The first example we'll look at is building and exposing an API endpoint in our Next.js application. To create a new API endpoint route, we will first need to create an api directory in our pages directory, and then every file we create in this api directory will be treated as an individual API endpoint.

Let's go ahead and create the api directory and a new file in this directory called posts.js. This endpoint will return a list of all the blog posts from our posts collection in the MongoDB database. The implementation for this route is as follows:

import { connectToDatabase } from "../../lib/mongodb";


export default async function handler(req, res){
    const {db} = await connectToDatabase();

    const data = await db.collection("posts").find({}).toArray();

    res.json(data);
}
Enter fullscreen mode Exit fullscreen mode

Go to the lib/mongodb.ts file and update the existing code to the following code:

import { MongoClient } from 'mongodb'

const { MONGODB_URI, MONGODB_DB } = process.env

if (!MONGODB_URI) {
  throw new Error(
    'Please define the MONGODB_URI environment variable inside .env.local'
  )
}

if (!MONGODB_DB) {
  throw new Error(
    'Please define the MONGODB_DB environment variable inside .env.local'
  )
}

/**
 * Global is used here to maintain a cached connection across hot reloads
 * in development. This prevents connections growing exponentially
 * during API Route usage.
 */
let cached = global.mongo

if (!cached) {
  cached = global.mongo = { conn: null, promise: null }
}

export async function connectToDatabase() {
  if (cached.conn) {
    return cached.conn
  }

  if (!cached.promise) {
    const opts = {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    }

    cached.promise = MongoClient.connect(MONGODB_URI, opts).then((client) => {
      return {
        client,
        db: client.db(MONGODB_DB),
      }
    })
  }
  cached.conn = await cached.promise
  return cached.conn
}
Enter fullscreen mode Exit fullscreen mode

Now, if we navigate to localhost:3000/api/posts, we'll see a result that looks like this:
localhost2

Finally, let's update the pages/index.ts file to use this JSON response and display the formatted data on the homepage.

import Head from 'next/head'
import { connectToDatabase } from '../lib/mongodb'
import { InferGetServerSidePropsType } from 'next'
import { title } from 'process';

export async function getServerSideProps(context) {
  const { db } = await connectToDatabase()

  const data = await db.collection("posts").find({}).toArray();

  const allposts = JSON.parse(JSON.stringify(data));

  return {
    props: { posts: allposts },
  }
}

export default function Home({ posts }) {

  console.log(posts);

  return (
    <div>
      <Head>
        <title>Nextbnb</title>
        <link rel="icon" href="/favicon.ico" />
        <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet"></link>
      </Head>

      <div className="md:container md:mx-auto">
        <p>All Posts</p>
        <ul>
          {posts.map(post => (
            <li key = {post._id}>{post.title} by {post.author_name} on {post.published_on}</li>
          ))
          }
        </ul>
      </div>

    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Finally, navigate to http://localhost:3000/ !

Tada ๐ŸŽ‰ Now you can see the posts collection data on the homepage of the application. This is just the rough presentation of the data on the frontend - you can make further changes to improve the UI.
collectionpost

Putting it all together

In this tutorial, we walked through the MongoDB Atlas and created a database with three different collections, learned how to quickly build a multipage application using ToolJet, and finally, we connected our MongoDB database to the Next.js application and executed queries.

If you have any questions or feedback, reach out through the ToolJet Slack community and let me know what you want to build with ToolJet and MongoDB.

Top comments (0)