How to build a Tour Diary app using Next.js and Cosmic JS


In this tutorial, I'm going to show you how to create a tour diary app using Next , Redux, Ant design and  Cosmic JS.

TL;DR

Download the GitHub repo.
Check out the demo.

Prerequisites

You will be required to install Node JS and npm before starting. Make sure you already have them installed.

Getting Started:

First, we will setup the bucket in Cosmic JS.

Setup bucket:

To create the bucket, login to Cosmic JS and click add 'new bucket'.

Select start from scratch.

Import Bucket Data:

Download this bucket.json file. And in Settings -> Import / Export Data, click "Add Import File" and choose the downloaded file. It will import all the Object Types and required data.

Now we will work on application. 

Doing everything using the existing git repo

You need to have git installed in your system in order to clone the repository. Once done run the following command through terminal or command line:

git clone https://github.com/cosmicjs/next.js-tour-diary
cd next.js-tour-diary
npm install
npm run dev

package.json will look like this.

What we’re installing and why

  1. We’re going to use Next and Redux libraries to create components and managing state in Next.
  2. We’re using next-routes package to navigate between our pages.
  3. We’re using antd package to create beautiful layouts using react components. We're using babel-plugin-import,  babel-plugin-inline-import, babel-plugin-transform-decorators-legacy for integrating ant design with next.
  4. We’re going to use cosmicjs library to handle our requests to our Cosmic JS bucket.
  5. react-draft-wysiwyg is used for editor & draft-js, immutable, html-to-draftjs, draftjs-to-html, react-html-parser has been installed to interact with its content and state.
  6. We're using react-medium-image-zoom for image zooming effect.
  7. We're using moment for time and date manipulation. 
  8. We're using cross-env for setting environment variables and babel-plugin-inline-dotenv for setting them by creating .env file in our project.
  9. We're using eslint and a predefined set of rules in eslint-config-rallycoding for code linting.
  10. We're using react-cookies for managing our redux store since it got destroyed in page reload.

Building our app

Once we'r done installing every required package by running npm install, let's start creating our app.

Setting up Eslint & Babel:

Let's create a .eslintrc.json file in our project root directory and past the below code in it:

Here we are setting the predefined rules from the rallycoding package we have installed.

Now let's create a .babelrc file in our project root directory and past the following code in it.

In the above code we are setting up our ant design and dotenv configuration.

Setting up .env file:

We need to create a .env file at the root of the project. It will load all the variables into process.env.

Here you will place the values for your bucket.

Setting up Cosmic Js JavaScript client: 

NOTE: This is using an older version of the Cosmic JS NPM module.  View the new 3.0 version of the module here.  We will be using Cosmic Js official JavaScript client for creating, reading, updating, deleting data from our bucket. You can read more about it by clicking here.

Create a folder with name cosmic in our root directory. Create a file config.js and cosmic.js in the cosmic folder we have just created.

In the cosmic/config.js file add the following code:

Here we are setting up our configuration for bucket by getting environment variables from the .env file we have previously created.

In the cosmic/cosmic.js file add the following code:

Here we are creating a generic functionality to interact with our bucket using cosmic js package. We will be using it through out the project.

Setting up Helper functions:

Let's create a folder with name Helper in our project root directory. Create Helper.js file in it and add the following code:

Here we are setting up our helper functions which we will be using through our the applications. The getCurrentDate function returns the current date. sortArr function sort the array on the basis of date. disabledDate function disabled the future dates in the datepicker. allowSpecificDates functions is being used in the tour details component to allow the selection of those dates only which are within the range of tour duration. In allowSpecificDates since our redux store got destroyed after page reload in the tour details page so we will be retrieving our content from the cookie we have saved and do the processing from it. We will discuss about it later in the article.

Setting up Redux Store:

Let's create a folder with name store in our root directory of the project. Here we will be saving all files related to our redux store.

Create store/constants.js file and add the following code:

Here we will be adding all our constants which we will be using in our redux store.

Create store/actions.js file and the add the following code:

Here we are adding action creators which will be returning an actions. You can learn more about it from here.

Create store/reducer.js file and add the following code:

Here we updating our store state with respect to the action we get.

Create store/saga.js file and add the following code:

We are using redux-saga as a middle layer for performing asynchronous actions. We will be calling our cosmic api functions which we have defined in cosmic/cosmic.js here and call the actions on the basis of result we will get from the cosmic api response.

Now let's discuss what's each of our function is performing. In all of these functions after performing the operation in our cosmic js bucket we are updating our redux store.

  1. In getTourData we are getting the list of tours from our bucket.
  2. In addNewTour we are first saving our media file to cosmic js bucket and the adding the new tour information to our bucket.
  3. In updateTour we are updating the tour information in our bucket.
  4. In deleteTour we are deleting the tour data from the bucket such as its timeline, media files.
  5. In getTourDetail we are retrieving the timeline for a particular tour.
  6. In addNewTourDetail we are adding the timeline to this tour in our bucket.
  7. In updateTourDetail we are updating the particular timeline of the tour.
  8. In deleteTourDetail we are deleting the timeline from the tour.
  9. In deleteMedia we are deleting the media file from the bucket.

Since everything we need related to our store is being set now let's create a redux store by creating a store/store.js file and adding the following code:

Here we are using next-redux-wrapper and next-redux-saga package for using redux and redux-saga in Next.

Setting up Components:

Since our redux store is being fully setup. Let's create our app components. First create a folder with name components in the project root directory.

wrapper.js

Create our wrapper component in components/wrapper.js and add the following code in it:

This will be our master layout for pages in which we are setting up header and its meta tags, footer and css for our application.

Now lets create folder with name Tour in components folder.

Tour.js 

Create Tour/Tour.js file and add the following code:

Here we rendering the tours list which we will get from the redux store and also adding the TourModal component in it for creating tours. 

TourModal.js

Let's create our TourModal component with file name Tour/TourModal.js and then add the below code in it:

This component will be used for creating and updating the tour. 

TourDetail.js

Create Tour/TourDetail.js file and add the following code:

Here we will rendering the tour timeline along with its details. We are rendering the TourDetailModal component in TourDetail component which we will be using for adding and updating the timeline. We are also update the tour details here.

TourDetailModal.js

Let's create our TourDetailModal component by creating a file in Tour/TourDetailModal.js and adding the following code in it:

We will be using this component for adding and updating timeline to our tour.

Setting up server and routes:

If you have noticed in our Tour component we are navigating to the dynamically created pages for each tour. For that we have to setup our server.js and routes.js file. Let's set them up.

routes.js

Create a routes.js in the project root directory and add the following code in it:

Here we are defining our main route and the route for showing tour details. We will be sending the tourId as a query string parameter in to our tour-detail page.

server.js

Create a server.js file in the project root directory and add the following code:

Setting up pages:

Since all our components are being set and ready to be used in the app. Let's move on to setting up out pages for the app in which we will be rendering our components.

Let's create pages/index.js and add the following code in it:

Here we are dispatching the getTour action which will be saving the list of tours we get from the cosmic js bucket to our redux store. This list will get rendered in our Tour component.

Now let's create pages/tour-detail.js page and add the following code:

Here are getting the tourId as a query parameter from which we will get the tour timeline details and render them in our TourDetails component.

Conclusion

So, this is an app where every scenario of Cosmic RESTful API using cosmic npm package, next & redux is covered. I hope you like the tutorial.  If you have any questions please reach out to Cosmic JS on Twitter and join the Cosmic JS Community on Slack.