Building a FileStorage Application using Xata, Cloudinary, and NextJs.

ADESANYA JOSHUA AYODEJI - Nov 23 '22 - - Dev Community

Storing files became necessary due to the ease with which pictures, videos, and other files can be generated; the smartphone era played a significant role in this; people want to save their memories so that they can always refer back to them in the future.

This article explains how to build a file storage application in Next.js, using Xata to provide the database service and Cloudinary to store the files.

Check out the Live demo of the application we will create.

Demo Picture

Demo | Code

Prerequisite

  • You should have a basic understanding of Javascript
  • You should have a basic knowledge of React Js and Next Js.

Tech Stack

  • NextJs is a React framework that builds on the functionality of React Js, it simplifies the creation of pages and API endpoints.
  • Cloudinary is a cloud media platform that allows users to upload files easily.
  • Xata is a serverless data platform that allows users to store data, search for data and get insights into the data.

Table of Contents

  • Project Setup and Installation
    • Next Js pages setup
    • Creating database and tables on Xata
    • Cloudinary
  • Connecting Cloudinary to the application
  • Connecting Xata to the application
  • Conclusion

Project Setup and Installation

NEXT JS PAGES SETUP

To begin, we'll create a new Next.js app, launch our terminal, create a new empty directory and execute the following command:

    npx create-next-app@latest
Enter fullscreen mode Exit fullscreen mode

Make sure you are in the correct directory and install the dependencies using a package manager like npm, yarn, or pnpm:

    npm i bcryptjs react-notifications 
Enter fullscreen mode Exit fullscreen mode

Create skeleton pages for the application

We will create the necessary pages needed for the application with the code below, we will create the following pages.

  • Index.js
  • all.js
  • files.js
  • photos.js
  • videos.js
  • login.js
  • signup.js

styles/global.css

Global css for all the pages.

styles/Home.module.css

components/Sidebar.module.css

CSS for the sidebar components.

pages/_document.js

We used the _document.js file to add font to our application.

components/Sidebar.js

The Sidebar component is used for switching between pages, and it is used on all the pages.

pages/index.js

The index page allows users to upload their files and view recently uploaded files.

pages/all.js

The all.js page is where users can view all their files.

pages/files.js

The files.js page is where users can view their documents such as pdf, word document, excel documents and others.

pages/photos.js

The photos page is where users can view all their pictures.

pages/videos.js

The videos page is where users can view all their videos.

pages/login.js

The login page is the access page to the application, and only authenticated users can access the application.

pages/signup.js

The signup page is where the users register to access the application.

CREATING DATABASE AND TABLES ON XATA

We need to log into xata.io to be able to create a database and add tables to the database.

Paper8

Sign in with GitHub or Google Mail or personal email.

Paper9

Add a workspace; we can do this by entering the workspace name.

Paper10

Add a Database, we can do this by entering the database name and selecting the preferred zone.

Paper1

Next, let's add a table. We can do this by selecting the database and clicking Add a table. Select empty table and enter a table name. We can add users table first.

Paper2

Let's also add fields to the table. The users table needs an id, email, and password field, while the files table needs an id, name, type, date, url, and userid field. The id field is created by default and autogenerated. Click on the highlighted icon and select the appropriate data type.

Paper3

The datatypes for the Users fields are

  • Email - String
  • Password - String

The datatypes for the Files fields are

  • Name - String
  • Type - String
  • Date - date
  • Url - String
  • Userid -String.

Users table

Paper4

Files table

Paper5

Copy workspace base API URL.

Paper6

To generate the API key, go to account settings, enter the name of the API key and click o save.

Paper7

CLOUDINARY
Signup on cloudinary.com and login to your account.

Get the cloudname on the dashboard and the presetname on the settings page.

Connecting Cloudinary to the application

We added the Cloudinary script to our index.js page during the page setup. Now, let's add the necessary code to upload files to Cloudinary and get the url link to our file.

Connecting Xata to the application

This application will do 4 significant actions on Xata: signup, login, save and retrieve files.

Setup API Routes on NextJS.
Before we set up our API routes, we need to add our .env file.

.env

XATA=Bearer <Insert your API KEY>
salt=<Insert anything>
database=<workspace base API URL>
Enter fullscreen mode Exit fullscreen mode

api/signup.js

The signup API route expects a request body from the client, it is a POST request, and the first thing it does is check if the email already exists; if it does, it returns an error message, but if it does not, it creates a new user in the database.

api/login.js

The login API route expects a request body, a POST request, and it gets the email needed to check if the user exists; if the user exists, the user object is sent to the client.

api/upload.js

The upload route API expects the request object, which contains the file name, file url, type, and other data; the upload API stores the file in the database. It is a POST request.

api/files

The files route API is a GET request. We need to retrieve the files we have stored in the database, which is what the files API route does. It uses the search query, which is the userid, to fetch all files associated with the user.

Integrate API routes with the pages

pages/signup.js

We have imported bcryptjs and react notifications to help with password hashing and the user experience. We made use of the useRef hook to get our input value.

The sign function is where the action is taking place; it checks if the email or password is empty and returns an error message if it is empty, then we use bcryptjs to hash the password, we send the credentials to our signup API route, and if the request is successful, we store the userid and email in the client using localStorage API, and redirect the user to the index page, if the user already exists, we display an error message.

pages/login.js

The log function checks if the email or password is empty and returns an error message If it is empty, we send the request to the login API route; then we use bcryptjs to compare the password; if the password is wrong, we display an error message, if the password is correct, we store the userid and email in the client using the localStorage API, and redirect the user to the index page.

pages/index.js

We set up our useState for the different types of files, and we also set up our useEffect to check if the user has been authenticated. We are doing this by checking the userid in the localStorage. We also get all the files when the page is refreshed, and we do this by calling the files API route inside the useEffect. We have also updated our showWidget function to store the url link and associated information we get when we upload our files to Cloudinary. We are using the upload API route for this inside the showWidget function. We are also getting the type of file by checking the extension of the files, which will help us classify the files into different categories. Finally, we use the different array categories for the file type to display the files on the page.

pages/all.js

The all page uses the api/files endpoint to get all the uploaded files and displays them on the page.

pages/files.js

The files page uses the api/files endpoint to get all the uploaded files, filters the result for documents like pdf and Microsoft word, and displays them on the page.

pages/photos.js

The photos page uses the api/files endpoint to get all the uploaded files, filters the result for the images, and displays them on the page.

pages/videos.js

The videos page uses the api/files endpoint to get all the uploaded files, and filters the results for videos, and displays them on the page.

For all the pages, we are checking if the user is authenticated inside the useEffect, we are also calling the files API route to get the files associated with the user. We use the useState to keep track of our files and display them on the page.

Conclusion

We built a fully functional file storage application using Xata, Cloudinary, and NextJs, where users can upload images, videos, documents, and other files.

Users can sign up and log in to the application to start using it; users' passwords are hashed for security, and only users can access the files they store in the application.

I hope you found this tutorial useful.

Thank you for reading.

Link to the demo - https://clouddrop.netlify.app/

Content created for the Hackmamba Jamstack Content Hackathon with Xata and Cloudinary.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .