Building an Instagram Clone in React-Native and Tailwind-CSS with a Ruby on Rails API only backend

Corey Gibson
Jan 7 · 7 min read

** This guide assumes basic React.JS knowledge and some exposure to Ruby on Rails**

Image for post
Image for post

I haven’t found a great resource for React-Native articles and building applications, so I figured that I would attempt to write a tutorial on building a React-Native app using a Ruby on Rails backend. We will be using Expo to build and manage the React-Native project. So let us just jump into the deep end. I am going to build out a quick frontend first then will connect to a Rails backend and display some seed data for the time being. Let’s get started!

$ expo init instaclone

after the project generates, make sure to change to the project directory let's install a few dependencies that will we be using. let’s use Tailwind-CSS for easy styling and I haven't used it with React-Native at this point so I figured that I would try it out. We will be using the package by TVke.

$ yarn add react-native-tailwindcss

At this point, we need to generate the tailwind.config.js file I am going to use the full install for the purpose of this tutorial

$ npx tailwind init --full

This will generate the full config of Tailwind with all the styles provided by Tailwind.

Next lets, install to handle all of our routings inside the application

$ yarn add react-router-native

and we also use Font Awesome to handle all the icons in this project

$ yarn add @fortawesome/fontawesome-svg-core
$ yarn add @fortawesome/free-solid-svg-icons
$ yarn add @fortawesome/react-native-fontawesome

We still need to install Axios to handle are API calls

$ yarn add axios

Okay, so our project should have everything it needs to start building. Let's fire up our server and launch an emulator to see our app.

$ yarn start 

At this point, you should be able to see the bare bones react-native application.

Okay, so I am going to handling all of my routings in the top-level App.js file, now we create a ./pages and ./components directory.

$ mkdir components pages

and in the components directory, I made a BottomNav component, and in the pages directory, I created all of the page views.

$ touch components/BottomNav.js pages/Home.js pages/Search.js pages/AddPhoto.js pages/Likes.js pages/MyPhotos.js

For now, I just added that basic boilerplate to each component that I made to work around the errors.

// *** Notice I did this for all of the above files that I made just // make sure all the names match ****import React from 'react'
import { View, Text } from 'react-native'
const Home = () => {
return (
export default Home

So, now we need to handle or basic routing through our application. Below you can see I import all my components for styling and routing.

Image for post
Image for post

So, now let's build out our BottomNav component and handle all of the links to different pages.

Image for post
Image for post

By now you should have something that looks like this.

Image for post
Image for post

and on each press of a button, you will be routed to a different page of the application. Okay, now we need data. We are going to start by using a Rails app and some seed data we will get to uploading photos and posting in another tutorial.

It’s time for Ruby on Rails!

In another directory lets create a new rails project that will be API only and use PostgreSQL out of the box.

$ rails new instaclone_backend --api --database=postgresql

After your new rails project is up and running lets $ cd instaclone_backend and generate our basic PhotoPost model. At this point we dont have a User model so for the time being we will just use a user name as a string and we will update the code when it comes time for a real user.

Steps we will take here…

  1. Create new database in PostgreSQL
  2. Create a basic PhotoPost model # don’t worry about the image active storage will handle that
  3. Install Rails Active Storage
  4. Migrate our database
$ rails db:create
$ rails g model PhotoPost username:string
$ rails active_storage:install
$ rails db:migrate

Now it’s time to hop into the editor and bask in the magic of rails… First we need to add a few gems that we will be using. Lets uncomment gem 'rack-cors' and gem 'image_processing and let’s add the gem 'faker' to the development test group in order to generate some fake usernames, also am going to use gem 'active_model_serializers' to generate well formatted JSON data that our API will consume.

Your Gem file should look like this.

Image for post
Image for post

Now run to a bundle install to install everything

$ bundle install

We still need to add the Active Storage to our ImagePost model this is is as simple as a single line of code in our model

Image for post
Image for post

Now we must configure a few small things in order to accept outside API request through rails and the ‘rack-cors’ gem. For the time being lets edit our ./config/initalizers/cors.rb to look like this which allows outside connections to access Rails and make any and every API request it want. ***NOTICE this must be changed when pushing to production or anyone that goes to the address of the backend will have access to the application***

Image for post
Image for post

Now that this is ready to go we are going to use active_model_serializers to handle the JSON formatting so we need to generate a serializer for our ImagePost model

$ rails g serializer ImagePost

This generated a ./serializers folder and a ./serializers/image_post_serializer.rb file, we should edit this file to handle the JSON info that will be include in the request made from our frontend.

Image for post
Image for post

What did we do here?

  1. we set the three attributes to be returned from our get request
  2. we set a conditional that returns the path to our image if an image is attached to the ImagePost.

Okay, so I also went and grabbed a few photos off of so I had a few high quality photos to use for dummy photos, and then added them to a folder called images and placed it inside the public directory.

$ mkdir ./public/images 

Now lets seed our database with some dummy data and set up our then set our frontend to make a request.

Image for post
Image for post

Here I make 100 ImagePosts using Faker and a random image from my images folder. Now lets run our seed file

$ rails db:seed

Now we just need to generate our controller and set up our index action.

$ rails g controller ImagePost index

This should have made a new controller file and populated it with an empty index action, let’s add two lines to that file to return all of the ImagePosts that currently exist in the database.

Image for post
Image for post

These two lines of code will handle finding all ImagePosts and the attached image all while preventing that dreaded N+1 query. At this point if we run our rails server we should be able to check that our JSON request and response.

$ rails s 

Let there be JSON!!!

Now let’s hop into the browser and test our API endpoint. Navigate to http://localhost:3000/image_post/index and you should see a nice piece of JSON with all our data.

Image for post
Image for post

If you see something similar to this you’re in great shape. Now let’s edit our React-Native app to make our request display our photos.

So, if you haven’t used hooks yet useState and useEffect may be foreign to you but it’s really not that bad.

const [posts, setPosts] = useState([])

This line of code creates a posts variable and sets the original value to an empty array, and also creates a function called setPosts that will be used in place of the traditional setState function.

The next piece of unfamiliar territory is useEffect which replaces React’s life cycle methods.

useEffect(()=>{// use effect written with the empty array as the second argument  // causes this to only run on the initial render},[])

Okay now to break out the code some I added a ./components/PhotoPosts.js to the project and that will handle each photo that is seen in our project.

Okay at this point everything should be working and when you click on the home button in our app we should see a list of all 100 posts in our database.


So if you made it this far you should have a working Ruby on Rails backend with a React-Native frontend that allows us to make a single API request to our local host and return all the images in our database.

This is part one of probably a six part tutorial with the aim to build a more full featured app. Please Stay tuned for more!

The Startup

Medium's largest active publication, followed by +707K people. Follow to join our community.

Corey Gibson

Written by

Full-Stack Software Engineer, Instructional Assistant at General Assembly NYC.

The Startup

Medium's largest active publication, followed by +707K people. Follow to join our community.

Corey Gibson

Written by

Full-Stack Software Engineer, Instructional Assistant at General Assembly NYC.

The Startup

Medium's largest active publication, followed by +707K people. Follow to join our community.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

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