How to Create an Instagram Photo Printing App in Node.js

Instagram API Lob API Nodejs Tutorial

In this tutorial, I will walk you through the process of creating a Node.js web application that will print and mail a 4x4 Instagram photo. The web application will allow a user to log in to their Instagram account, randomly choose a recent photo from their feed, and then provide a shipping address to mail the photo.

View Demo

The app will be written in Node.js and will use the very popular Express.js framework. We will be starting with a blank project, and by the end will have a fully functioning web application.
We will be using two main APIs to build this application. The Instagram API, which will allow us to log in to an Instagram account and select images from a user’s recent feed, and the Lob Print & Mail API, which will handle the printing and shipping of our 4x4 Instagram photos.

NOTE: This whole project is available in a public repository on GitHub. I suggest downloading it first and taking a look at the code before continuing the tutorial.

The Main Pieces

Prerequisites

You will need the following before you can start this tutorial:

  • A basic understanding of Node.js and JavaScript.
  • A basic understanding of how JavaScript Promises work. If you haven’t used them before don’t worry, here’s a quick guide.
  • NPM and Node.js installed.
  • A Lob API key.
  • A registered Instagram Developer account.

Instagram Registration

In order to use the Instagram API, you need to first register your application at the developer center. Once you have registered your application, they will provide you with a client_id and a client_secret, which we will need later.

Part of the registration form will ask for a redirect_uri. This is where the user will be redirected after they successfully sign into their Instagram account. For now, set this value to http://localhost:3000/handleauth, which will point to our local app during development.

Lob Registration

Sign up for a free Lob account by visiting the registration page. Once registered, you can find your Test API Key on the settings page. The Test API Key works the same as the Live, but no mail is actually printed or shipped until you use your Live API Key.

Create Project

If you already have an express.js project setup you can skip the the next section. If not, open up a terminal and let’s get started. 

mkdir instagram && cd instagram
npm init

When you run npm init it will ask you a bunch of questions; just press enter for all of them except when it asks you for entry point: (index.js); set that to app.js.

Install Dependencies

npm i express --save
npm i bluebird --save
npm i body-parser --save
npm i cookie-parser --save
npm i instagram-node --save
npm i jade --save
npm i lob --save

These are all the node modules we will be using to create the Instagram photo printing app.

Create Server

Create a file called app.js file in the root directory of your project.

var express       = require('express');
var path          = require('path');
var cookieParser  = require('cookie-parser');
var bodyParser    = require('body-parser');
var instagram     = require('./instagram');
var app           = express();

/* App Setup */
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());

/* Include our Instagram Module */
app.use('/', instagram);

app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function() {
  console.log('Express server listening on port ' + server.address().port);
});

module.exports = app;

Notice we are telling the app to run on port 3000. This matches up with the redirect URL you submitted when registering your Instagram app.

Template Files

Create a folder called views in the root directory of your project, next to the app.js file. This is where we will place the following Jade template files. If you haven’t used Jade before it’s a pretty simple templating engine that comes by default with Express.js. Learn more here.

We are also using Bootstrap to provide basic styling and layout for the application. Check out the Bootstrap website for more information on the CSS classes we are using in the template files.

layout.jade

Create a file called layout.jade with the following code. This is the basic HTML structure for our app.

doctype html
html
  head
    title Instagram Photo Printer
    link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css')

  body

    nav.navbar.navbar-inverse.navbar-static-top
      div.navbar-header
        a.navbar-brand(href="/") Instagram Photo Printer

    div.container
      block content

index.jade

Create a file called index.jade inside the views folder with the following code. Notice that we are using a template variable called showLogin. If this is true, we are going to show the user a button so that they can log in to their Instagram account. Otherwise, we will show them a random picture from their account and shipping form for their Instagram photo.

Don’t worry too much about this right now. It will make more sense once we start writing code.

extends layout

block content

  if showLogin
    div.row
      div.col-md-12.text-center
        h1 Instagram Photo Printer
        p Before you can print and mail a photo, you need to authorize your Instagram account.
        a(href="/authorize-user" class="btn btn-primary") Login to Instagram
  else
    div.row
      div.col-md-6
        img(src= image, width="250px")
        div
          br
          a.btn.btn-default(href="/") Random Photo

      div.col-md-6
        h1 Print & Mail Photo

        form(action="/send-photo", method="post")
          div(class="form-group col-md-12")
            label Name
            input(
              type="text"
              class="form-control"
              name="name"
            )
          div(class="form-group col-md-12")
            label Address
            input(
              type="text"
              class="form-control"
              name="address"
            )
          div(class="form-group col-md-4")
            label City
            input(
              type="text"
              class="form-control"
              name="city"
            )
          div(class="form-group col-md-4")
            label State
            input(
              type="text"
              class="form-control"
              name="state"
            )
          div(class="form-group col-md-4")
            label Zip
            input(
              type="text"
              class="form-control"
              name="zip"
            )
          div(class="form-group col-md-12")
            input(type="hidden", value=image, name="image")
            button(type="submit", class="btn btn-primary") Mail Photo >

complete.jade

The last template file we will need is complete.jade, which will show a success message and a preview link once the user has successfully filled out the form. If there was an error, it will show that as well.

extends layout

block content
  div.row
    div.col-md-12.text-center
      if error
        div.alert.alert-danger
          p= error
      else
        div.alert.alert-success
          p Success! Your photo has been sent. You can see a preview here:
            a(href=url, target="_blank")= url

      a.btn.btn-primary(href="/") Send Another Photo
Russell Taylor

Comments

Comments(5)

ah12

Does the demo actually mail a postcard out? 

Pbishop

Hello Russell,

I have ran through the files, downloaded the dependencies, but am still getting an errror on server run.

::

C:\download\DevOps\instagram>node app.js

C:\download\DevOps\instagram\node_modules\express\lib\router\index.js:458

      throw new TypeError('Router.use() requires middleware function but got a

            ^

TypeError: Router.use() requires middleware function but got a Object

    at Function.use (C:\download\DevOps\instagram\node_modules\express\lib\router\index.js:458:13)

    at EventEmitter.<anonymous> (C:\download\DevOps\instagram\node_modules\express\lib\application.js:219:21)

    at Array.forEach (native)

    at EventEmitter.use (C:\download\DevOps\instagram\node_modules\express\lib\application.js:216:7)

    at Object.<anonymous> (C:\download\DevOps\instagram\app.js:28:5)

    at Module._compile (module.js:460:26)

    at Object.Module._extensions..js (module.js:478:10)

    at Module.load (module.js:355:32)

    at Function.Module._load (module.js:310:12)

    at Function.Module.runMain (module.js:501:10)

C:\download\DevOps\instagram>

::

I think my App.js \ var instagram = require('./instagram') need to be looked at.

Thanks for posing this, and all the best.

Peter

Pbishop

Hello Russell,

I have ran through the files, downloaded the dependencies, but am still getting an errror on server run.

::

C:\download\DevOps\instagram>node app.js

C:\download\DevOps\instagram\node_modules\express\lib\router\index.js:458

      throw new TypeError('Router.use() requires middleware function but got a

            ^

TypeError: Router.use() requires middleware function but got a Object

    at Function.use (C:\download\DevOps\instagram\node_modules\express\lib\router\index.js:458:13)

    at EventEmitter.<anonymous> (C:\download\DevOps\instagram\node_modules\express\lib\application.js:219:21)

    at Array.forEach (native)

    at EventEmitter.use (C:\download\DevOps\instagram\node_modules\express\lib\application.js:216:7)

    at Object.<anonymous> (C:\download\DevOps\instagram\app.js:28:5)

    at Module._compile (module.js:460:26)

    at Object.Module._extensions..js (module.js:478:10)

    at Module.load (module.js:355:32)

    at Function.Module._load (module.js:310:12)

    at Function.Module.runMain (module.js:501:10)

C:\download\DevOps\instagram>

::

Can I get you to confirm the following:

Under the App.js file -  var instagram = require(./instagram)

 

Thanks again and great post!

Peter

line154

At a glance, this article looks really helpful. Can't wait to sit and read through the whole thing! 

MH Raihan

Hi, I've problem , instagram api does not works for me. please help me :(

var express     = require('express'),

    instagram   = require('instagram-node').instagram(),

    app         = express();

// instagram configure

instagram.use({

    client_id: 'my-client-id',

    client_secret: 'my-client-secret'

});

// route

app.get('/', function(req, res){

    instagram.media_popular(function(err, medias, remaining, limit){

        res.json(medias);

    });

});

// server running

app.listen(8000,function (err) {

  console.log("listening on port: " + 8000);

});