In this tutorial, we will learn how to create a server. We will begin without express
and then strengthen the server using express
. After that, we will see how to upload images to Cloudinary from the app we have created.
I assume that you already understand the basics of Node.js
, express
and nodemon
so we will just go straight to the practical parts.
Install Node.js and NPM
If you haven’t yet done so, you’ll need to install Node and npm on your machine.
- Go to the Node.js website
- Click on the recommended download button

When the download is complete, install Node using the downloaded .exe
file (it follows the normal installation process).
Check if the installation was successful
- Go to your terminal/command prompt (run as administrator if possible)
- Type in each of the following commands and hit Enter
node -v
npm -v
Your output should be similar to the image below:

The version may be different but that’s OK.
How to Create a Node Server without Express
For the rest of this tutorial, I will be using VS code as my editor. You can use whatever editor you choose.
Let’s start by creating a project directory. Open a terminal and type the following to create a directory and open it:
mkdir server-tutorial cd server-tutorial
I named my project directory server-tutorial
, but you can name yours as you please.
In the terminal, type npm init
. Hit the Enter
button for all prompts. When completed, you should have a package.json
file seated in your project directory.
The package.json
file is just a file with all the details of your project. You don’t have to open it.
Create a file called index.js
.
In the file, require the HTTP
module like so:
const http = require('http');
Call the createServer()
method on it and assign it to a constant like this:
const server = http.createServer();
Call the listen()
method on the server constant like this:
server.listen();
Give it a port to listen to. Now this could be any free port, but we will be using port 3000
which is the conventional port. So we have this:
const http = require('http');
const server = http.createServer();
server.listen(3000);
Basically, that is all you need do to create a server.
How to Test the Server
In your terminal (should be in the project directory), type node index.js
and hit the Enter
button.
Open a new tab in postman
or any web browser
and in the address bar, type http://localhost:3000/
, and hit the Enter
button. (I will be using postman because of its extended functionality outside the box.)
You will notice that your browser or postman keeps loading indefinitely like so:
Yay! That is fine. Our Server is up and running.
But it’s boring already. We need to make the server talk to us.
Let’s get to it immediately.
How to Send Back a Response from the Server
Back in the code, add the following to const server = http.createServer();
:
(request, response) => {
response.end('Hey! This is your server response!');
}
So we now have:
const http = require('http');
const server = http.createServer((request, response) => {
response.end('Hey! This is your server response!');
});
server.listen(3000);
In basic terms, the request
object tells the server
that we want something, the response
object tells us what the server
has to say about our request
, and the end()
method terminates the communication with the server
response
.
Hopefully, that makes sense!
Now, test the server again following the steps we outlined above and your server should be talking to you. This is my output:
Feel free to change the string as you wish.
Use Control/Command + C
to terminate the server and run node index
to start the server again.
Looking Sharp! Right? All good…
How to Create a Node Server With Express
In this section, we want to make our lives easier by using Express
and Nodemon
(node-mon or no-demon, pronounce it as you wish).
In the terminal, install the following:
npm install express --save
npm install nodemon --save-dev
Create a new file named app.js
or whatever suits you
In the file,
- Require express like so:
const express = require('express');
2. Assign the express method to a constant like this:
const app = express();
3. Export the app constant to make it available for use in other files within the directory like so:
module.exports = app;
So we have:
const express = require('express');
const app = express();
module.exports = app;
In the index.js
file, require the app
we exported a while ago:
const app = require('./app');
Next, set the port using the app like so:
app.set('port', 3000);
And replace the code in the http.createServer()
method with just app
like this:
const server = http.createServer(app);
This directs all API management to the app.js
file helping with separation of concerns.
So our index.js
file now looks like this:
const http = require('http');
const app = require('./app');
app.set('port', 3000);
const server = http.createServer(app);
server.listen(3000);
Back in our app.js
file, since we have directed all API management to it, let’s create an endpoint to speak to us like before.
So before the module.exports = app
, add the following code:
app.use((request, response) => {
response.json({ message: 'Hey! This is your server response!' });
});
We now have:
const express = require('express');
const app = express();
app.use((request, response) => {
response.json({ message: 'Hey! This is your server response!' });
});
module.exports = app;
Ahaaa… It’s time to test our app.
To test our app, we now type nodemon index
in our terminal and hit the Enter
button. This is my terminal:
Do you notice that nodemon gives us details of execution in the terminal unlike Node? That’s the beauty of nodemon.
You can now go to postman
or any browser
and in the address bar, type http://localhost:3000/
and hit Enter
. See my output:
Walah! It’s working.
Now more reasons to use nodemon. Go to the app.js
file and change the message
string to any string on your choice, save, and watch the terminal
.
Wow… It automatically restarts the server. This was impossible with Node. We had to restart the server ourselves.
How to Secure the Server and Make it Future-Proof
In the index.js
file, replace all the code with the following:
const http = require('http');
const app = require('./app');
const normalizePort = val => {
const port = parseInt(val, 10);
if (isNaN(port)) {
return val;
}
if (port >= 0) {
return port;
}
return false;
};
const port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
const errorHandler = error => {
if (error.syscall !== 'listen') {
throw error;
}
const address = server.address();
const bind = typeof address === 'string' ? 'pipe ' + address : 'port: ' + port;
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges.');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use.');
process.exit(1);
break;
default:
throw error;
}
};
const server = http.createServer(app);
server.on('error', errorHandler);
server.on('listening', () => {
const address = server.address();
const bind = typeof address === 'string' ? 'pipe ' + address : 'port ' + port;
console.log('Listening on ' + bind);
});
server.listen(port);
process.env.PORT
makes the app dynamic so that it can run any port assigned to it in the future when hosted on a live server.
The normalizePort
function returns a valid port, whether it is provided as a number or a string.
The errorHandler
function checks for various errors and handles them appropriately — it is then registered to the server.
A listening
event listener is also registered, logging the port or named pipe on which the server is running to the console.
YooH! Our server is more secure and robust right now. Notice that nodemon also displays the port we are listening on.
There you have it, a simple, secure and robust Node.js server.
How to Upload Images to Cloudinary
Now that we have a cool server running, let’s learn how we can save our images on Cloudinary. This will just be a basic introduction so it should be fun 😊.
Cloudinary helps developers across the world manage images with minimal effort.
How to Create a Cloudinary Account
To create an account, go to the Cloudinary Website.
- Click the
sign up
button on thetop right
. - Fill the form that shows up accordingly.
- Submit the form using the
Create Account
button. - Check your email to finish up by validating your email
You should be able to access your dashboard which looks like mine below:
Notice the Account details
. You shouldn’t reveal this information to anyone. I am showing it to you here because this is a temporary account that I’m using only for the purposes of this tutorial.
Checkout the Media Library
tab too. This is where the uploaded images will appear.
If you have all these showing, then let’s rock and roll…
How to Install Cloudinary in Our Project
Open your terminal and navigate into the project directory.
Execute the following command to install Cloudinary
:
npm install cloudinary --save
How to Setup Cloudinary in Our Project
In the app.js file, require cloudinary
below the const app = express();
like so:
const cloudinary = require('cloudinary').v2
Next, add the configuration details from the account details on your dashboard like this:
cloud_name: 'place your cloud_name here',
api_key: 'place your api_key here',
api_secret: 'place your api_secret here',
This is what I have:
// cloudinary configuration
cloudinary.config({
cloud_name: "dunksyqjj",
api_key: "173989938887513",
api_secret: "ZPLqvCzRu55MaM1rt-wxJCmkxqU"
});
How to Create an EndPoint to Upload an Image
To avoid bugs in our code, first replace the existing API with the following code:
app.get("/", (request, response) => {
response.json({ message: "Hey! This is your server response!" });
});
It is basically the same but this time, we are using the get
verb in place of the use
verb and we added a root end-point (/
).
Next, just before the module.exports = app;
line, we will be creating our image-upload
API.
Let’s start by placing this code there:
// image upload API
app.post("/upload-image", (request, response) => {});
Basically, this is how we set up an API. The API makes a POST
request
to the server
telling the server
that the request
should be handled with a degree of security. It uses two parameters to make this request: an end-point
(/upload-image) and a callback function
((request, response) => {}).
Let’s breathe life into the API by building out the callback function
.
How to Build the Callback Function
Install body-parser
This npm package enables us to handle incoming requests using req.body
or request.body
as the case may be. We will be installing body-parser
using the following code:
npm install --save body-parser
Configure body-paser for our project
Require body-parse in the app.js like so:
const bodyParser = require('body-parser');
Next, add the following code to set its json
function as global middleware for our app like so:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
We can now handle our request body appropriately.
Back to Building Our Function
In the function, add the following code to collect any data (images) entered by a user:
// collected image from a user
const data = {
image: request.body.image,
};
Next, upload the image to cloudinary
using the following code:
cloudinary.uploader.upload(data.image);
Basically, this is all we need to upload our image. So our app.js
looks like this:
const express = require("express");
const app = express();
const cloudinary = require("cloudinary").v2;
const bodyParser = require('body-parser');
// body parser configuration
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// cloudinary configuration
cloudinary.config({
cloud_name: "dunksyqjj",
api_key: "173989938887513",
api_secret: "ZPLqvCzRu55MaM1rt-wxJCmkxqU"
});
app.get("/", (request, response) => {
response.json({ message: "Hey! This is your server response!" });
});
// image upload API
app.post("/image-upload", (request, response) => {
// collected image from a user
const data = {
image: request.body.image,
}
// upload image here
cloudinary.uploader.upload(data.image);
});
module.exports = app;
Now this looks good and it works perfectly. You can test it out using postman
. But it’s would be awesome if our app could give us feedback when it’s done handling our requests, right?
To make this happen, we will add the following then...catch...
block to the cloudinary upload like so:
// upload image here
cloudinary.uploader.upload(data.image)
.then((result) => {
response.status(200).send({
message: "success",
result,
});
}).catch((error) => {
response.status(500).send({
message: "failure",
error,
});
});
So our final code will be:
const express = require("express");
const app = express();
const cloudinary = require("cloudinary").v2;
const bodyParser = require('body-parser');
// body parser configuration
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// cloudinary configuration
cloudinary.config({
cloud_name: "dunksyqjj",
api_key: "173989938887513",
api_secret: "ZPLqvCzRu55MaM1rt-wxJCmkxqU"
});
app.get("/", (request, response) => {
response.json({ message: "Hey! This is your server response!" });
});
// image upload API
app.post("/image-upload", (request, response) => {
// collected image from a user
const data = {
image: request.body.image,
}
// upload image here
cloudinary.uploader.upload(data.image)
.then((result) => {
response.status(200).send({
message: "success",
result,
});
}).catch((error) => {
response.status(500).send({
message: "failure",
error,
});
});
});
module.exports = app;
How to Test our API
Create a folder/directory in the root directory and name it images
like so:
mkdir images
Copy an image of your choice to this folder. (Now, the path to your image relative to the app.js file should look like this: "images/<your-image.jpg">
.)
Now let’s proceed to postman
.
- In the address bar, enter this:
http://localhost:3000/image-upload
- Set the
Header
Key toContent-Type
and value toapplication/json
- Set the
body
to thejson
data we declared in our code like so:
{
"image": "images/oskar-yildiz-gy08FXeM2L4-unsplash.jpg"
}
Hit the Send
button and wait for the upload to complete and get your response:
Now, this is the result. The image now has a unique public_id
which is randomly generated by Cloudinary and a secure_url
which is globally accessible (you can load it in your browser to see).
Finally, checking the Media Library
tab on your Cloudinary dashboard, you should have a new image with a new
badge on it. This will have a unique id that matches the public_id
we saw in the postman result above just like in the image below:
Walah! We are persisting images without stress…That feels good.
Well, one more thing – SECURITY!
Our Cloudinary configuration details rea exposed in our app.js file. If we push our project to GitHub, it becomes publicly available to anyone who cares to check it out. And that becomes a problem if it gets into the wrong hands.
But don’t worry about a thing here, there is a fix for almost everything in this space. We will be using the dotenv
npm package to hid our configurations from the public.
How to Secure Our Configurations with dotenv
First, you’ll need to install dotenv if you haven’t already:
npm install dotenv --save
Then require dotenv
in app.js
like so:
require('dotenv').config()
Create a new file in the root directory and name it .env
.
In the file, enter your Cloudinary configuration details like so:
CLOUD_NAME=dunksyqjj
API_KEY=173989938887513
API_SECRET=ZPLqvCzRu55MaM1rt-wxJCmkxqU
In the app.js file, we will access the configurations in the .env
file via the process.env
property like so:
// cloudinary configuration
cloudinary.config({
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.API_KEY,
api_secret: process.env.API_SECRET
});
This is my app.js
code at the moment:
const express = require("express");
const app = express();
const cloudinary = require("cloudinary").v2;
const bodyParser = require('body-parser');
require('dotenv').config()
// body parser configuration
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// cloudinary configuration
cloudinary.config({
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.API_KEY,
api_secret: process.env.API_SECRET
});
app.get("/", (request, response, next) => {
response.json({ message: "Hey! This is your server response!" });
next();
});
// image upload API
app.post("/image-upload", (request, response) => {
// collected image from a user
const data = {
image: request.body.image,
}
// upload image here
cloudinary.uploader.upload(data.image)
.then((result) => {
response.status(200).send({
message: "success",
result,
});
}).catch((error) => {
response.status(500).send({
message: "failure",
error,
});
});
});
module.exports = app;
Let’s test our app again to make sure that nothing is broken. Here is my result:
I now have two of the same image but with different public_id
s.
And that is it!
Yeeeh! Our application is more secure than it was when we started.
Conclusion
In this tutorial, we went through the steps involved in creating a server using just Node.js. And after that, we improved our server using Express and nodemon.
Finally, we saw how to upload an image to Cloudinary through our Express application and how our configuration details are secured using the dotenv
package.
This is just an introduction. You can do a whole lot more if you play around with this application.
You can find the server creation code here.
And the image upload codes are available here.
Thank you for your time. 😊