Create Memes Generator with NodeJS

Programmer101N
May 7 · 5 min read

What we need for this tutorial.

  1. HTML and CSS
  2. Some Javascript
  3. Nodejs and Express
  4. Axios

Let’s create a folder named meme_generator and initialize node project by typing npm init -y

Now we have our NodeJS project initialized, Let’s open code in that folder and setup our express and webservers config.

I’m going to create a index.js, public and views directory.

  • Public directory will store our static files like js, css, images etc.
  • Views directory will store our views(webpages).
  • Index.js will contain code for our server.

First let’s setup our express server. Let’s install some modules in that folder by typing npm install express ejs axios lodash.

  • Express will create our server.
  • ejs is a templating module.
  • axios is a http request library which will make requests to imgflip api.
  • lodash is some functions for list that we’re gonna need.

Now that we installed our modules, Let’s open our index.js and write some code.

// IMPORTS
const express = require('express');
const axios = require('axios').default;
const _ = require('lodash');

Now we have our code and Server code ready. To run it we’re gonna need Nodemon(a library which reruns file when code is changed). Let’s install this globally. npm install -g nodemon

Now let’s run this index.js. Type nodemon index.js in your terminal.

If you open browser and go to http://localhost:3000. A message will show up.

cannot get '/'

It means our server is running correctly. Now let’s setup some routes.

In this I’m gonna create two routes.

  • ’/’ will contain our meme generator.
  • ‘/generate’ will have method POST and send request to imgflip API and returns response.
// IMPORTS
const express = require('express');
const axios = require('axios').default;
const _ = require('lodash');

// CONSTANTS
const app = express();

// MIDDLEWARES
app.use(express.json()); // This will parse json payload.
app.use(express.urlencoded({extended: true}); // This will parse urlencoded payload.
app.use(express.static('public')); // This will serve public directory on our server.
app.set('view engine', 'ejs'); // So express uses ejs as its templating engine.

// Routes
app.get('/', (req, res) => {
return res.render("index");
});

app.post("/generate", (req, res) => {
return res.send("Hello World!");
});

// Listeing to server
app.listen(3000, () => {
console.log("Server is running on http://localhost:3000");
});

Now our code is setup let’s dive into our frontend. Create a file named index.ejs in your views directory.

Write some code to make post request to /generate route with params of template_id, username, password, text0, text1 with form-urlencoded encoding type. Like in below code block.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Input</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="d-flex">
</div>
<form action="/generate" method="POST" enctype="application/x-www-form-urlencoded">
<div class="input-container">
<label for="">ID</label>
<input id="template_id" required name="template_id" type="text">
</div>
<div class="input-container">
<label for="">Username</label>
<input required name="username" type="text">
</div>
<div class="input-container">
<label for="">Password</label>
<input required name="password" type="password">
</div>
<div class="input-container">
<label for="">Upper text</label>
<input required name="text0" type="text">
</div>
<div class="input-container">
<label for="">Lower Text</label>
<input required name="text1" type="text">
</div>
<button type="submit" class="btn-primary">
Send
</button>
</form>
</div>
</body>

</html>

Let’s style this now, Create style.css in your public directory.

.container{
display: flex;
flex-direction: column;
}

.input-container{
margin: 15px;
display: flex;
flex-direction: column;
width: 30%;
}

.input-container label{
font-size: 24px;
font-family: 'Consolas', sans-serif;
font-weight: bold;
}

.input-container input{
border-radius: 25px;
padding: 10px;
border: 1px solid grey;
}

.btn-primary{
width: 30%;
height: 50px;
border: 1px solid white;
border-radius: 15px;
margin: 15px;
background-color: rgb(4, 156, 194);
color: white;
cursor: pointer;
}

.d-flex{
display: flex;
}

.d-flex img{
width: auto;
height: 100px;
margin: 10px;
border: 1px solid black;
cursor: pointer;
}

If you go to / route in your browser you will see this .

Now let’s setup our POST route. In index.js file. Make an request to imgflip api and pass the params that we have got when we send request from our index page of our server.

app.post("/generate", (req, res) => {
axios
.post(
"https://api.imgflip.com/caption_image",
{},
{
params: {
template_id: req.body.template_id,
username: req.body.username,
password: req.body.password,
text0: req.body.text0,
text1: req.body.text1,
},
}
)
.then((response) => {
return res.send(`<img src=${response.data.data.url}>`);
}).catch((e) => {
return res.status(403).send("403 Client Error")
});
});

NOTE: You will need username and password for making a request to imgflip api, Create your account on imgflip

Now that we have our POST route fully complete, Let’s create our frontend.

Let’s get all memes template from imgflip api and display 10 random meme_template which our user can select. Go to your / route and write this code.

app.get("/", (req, res) => {
axios
.get("https://api.imgflip.com/get_memes")
.then((memes) => {
return res.render("index", {
memes: _.sampleSize(memes.data.data.memes, 10)
});
})
.catch((e) => {
return res.status(500).send("500 Internal Server Error");
});
});
  • sampleSize method takes list as argument and number of size and gives number of random memes.
  • if there is error this will generate internet server error message.

Now let’s iterate and display image in our index view.

<div class="container">
<div class="d-flex">
<% for(const i of memes){ %>
<img class="meme_image" id=<%= i.id %> src=<%= i.url %>>
<% } %>
</div>
<form action="/generate" method="POST" enctype="application/x-www-form-urlencoded">
...
</div>

Now we want to add event listener to all image so that when we click on image, it’s id will change on click.

...
</body>

Now our project is complete. If you click on a image and type in your username and password and text and click Submit your meme will be generated.

You can download this source code from my Github.

Visit this Project on Github

Also Check out my blog, Here is the Link

Geek Culture

Proud to geek out. Follow to join our +500K monthly readers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store