Tutorial: Tomodachi — Contacts Management connecting Heroku, NodeJS, Postgres & React JS/Native


Realized I haven’t published an open-source tutorial in a long, so preparing a well documented tutorial. Will try to keep short and insightful for everyone. Maybe a Youtube series soon.
For test: Heroku App and Play Store
Github: Tomodachi is where the codebase is and this tutorial will work in tandem with the repo rather than full-blow step wise guide.
Tomodachi is a dummy application built using Node, React and Postgres with addition of React-Native to the system. The end-goal is to allow user to enter Contacts of their friend circle after Logging in with Facebook with basic features to edit and delete them.
Let’s start with the Backend:

Notice I am using concurrently to run the React app and Server at the same time. The –kill-others-on-fail flag will kill other processes if one exits with a non zero status code.
Install nodemon globally and the server dependencies:
npm i nodemon -g
yarnInstall heroku if you plan to use it:
npm install -g heroku-cliheroku create <app_name>
Currently, we have two applications. If we don’t set up CORS, our React application will not be able to communicate with the backend. We will use the Node.js library cors in
app.jsand by setting origin to true, we have allowed any origin to access the resource.methodsis used to control Access-Control-Allow-Methods CORS header. With the propertycredentialswe are controlling the Access-Control-Allow-Credentials CORS header. The lastexposedHeadersis used to indicate which headers can be exposed as part of the response.

I am using Passport package for the OAuth authentication over /api/auth/facebook. It requires configuration of some parameters which you can get from https://developers.facebook.com

Now the clientID and clientSecret is set in Repo through .env variables as
process.env.facebook_api_keyandprocess.env.facebook_api_secretby setting them as:
heroku config:set facebook_api_key=api-keyheroku config:set facebook_api_secret=api-secret
But, for convenience, you can set them in configuration/config.js and use them as:
clientID: config.facebook_api_key,clientSecret: config.facebook_api_secret
Once we Token from the frontend, we use passport-facebook-tokento get the access Token. Notice that localhost:3000 is the ReactJS client. Next, for new user, we insert the id and Name to users database on Postgres.
As we are using Postgres, we need to setup two table over a database, users and contacts, and as we will be deploying to Heroku, need need to setup Postgres over Heroku and use it’s connection String with SSL set to true for Postgres client.
heroku addons:create heroku-postgresql:hobby-devTo Push your Local DB:
heroku pg:push <database_name> DATABASE_URLAs we will be applying the connectionString through environment variable as
connectionString = process.env.DATABASE_URL

Next, when passing the payload back to client, we pass a JWT token based on user id and “my-secret” as the key expiring at 60x120.
jwt.sign({id: auth.id},"my-secret",{expiresIn: 60 * 120});Now, we callback /api/contacts/get/:id endpoint to get the contact list based on user id. But it requires passing Bearer Token which we have already sent to the client when logging in for verification.
jwt.verify(token, "my-secret", {expiresIn: 60 * 120})If the token is valid, we select the contacts based on the user id from contacts table and send it back.
Now, other major endpoints are: /api/contacts/add ,/api/contacts/delete/:id , /api/contacts/update/:id to add, delete and edit the contacts table based on the user id after JWT token verification. The endpoints are SQL injection protected by using placeholder scheme but needs further protection.
Now, to serve the Backend and database, the scheme is deployed to Heroku, thus requires the configuration as:
const port = process.env.PORT || 5000;
if (process.env.NODE_ENV === "production") { app.use(express.static(path.join(__dirname, "client/build"))); app.get("*", function(req, res) { res.sendFile(path.join(__dirname, "client/build", "index.html"));});}app.listen(port, () => console.log(`Listening on port ${port}`));
Also, Make sure you Update the CallBack URL over the Facebook Dev Console in
Products/Facebook Login/Settingswith new Heroku Url Callback. Also, make sure to addApp Domain and Website Site URL inSettings/Facebook Login/Settings
Now for the React Frontend:

Head over to client folder. The key to using an Express back-end server with a project created with create-react-app is to use a proxy. This tells the Web-pack development server to proxy our API requests to our API server, given that our Express server is running on localhost:5000in dev mode. Make sue to have HTTPS=true in .env file for local development.
We will majorly be using Hooks and useState instead of LifeCycle components and styled-components for CSS-in-JS.
What is a Hook? A Hook is a special function that lets you “hook into” React features.
What does calling
useStatedo? It declares a “state variable”. Our variable is calledcountbut we could call it anything else, likebanana. This is a way to “preserve” some values between the function calls —useStateis a new way to use the exact same capabilities thatthis.stateprovides in a class.
In src/App.jsif the isAuthenticated state variable is false, Login Button is shown and onClicking it, react-facebook-login is called to send the callback response accessToken to Express Backend using axioswhich will receive the x-auth-token header and user Data. Then the received id is sent back to hit the api to get the contactsList along with the bearer token just received. If response is sent back, isAuthenticated is set to true rendering the ContactList.
The avatar and user Name is rendered on Top right corner with Contact List at the center along with react-floating-action-button on bottom right corner, which onClick shows rodal for Modal to Add Contact.
If valid values are sent by onClick Send button over Add Contact Modal, endpoint is hit with the JWT token and payload and if response is sent back, the modal is closed with the Contact List populated. OnClicking a list key, ContactInfo component is shown with details and buttons to edit and delete.
On clicking delete, endpoint is called with again JWT token and id to delete the particular value.Also, on clicking edit, Edit modal is shown following same process as Add Contact Modal, but only updating the parameters.If the process is successful, the current Contact Info is popped off the render view in both cases.
Finally, for the React-Native Frontend:

Head over to react-native-app folder. The directory is independent to the others, cause well it is for Mobile app, what do you expect?
In future, might add Auto-Login cause we have already passed the token, just AsyncStorage might do the work.
As FbLogin is the root view, we initially navigate to it, which renders the Login Button and onPressing it, react-native-fbsdk is called to get the accessToken and we send it to Express Backend using axioswhich will receive the x-auth-token header and user Data. Then the received id is sent back to hit the api to get the contactsList along with the bearer token just received. If response is sent back, we render ListView by calling Action and passing it the props.

Make sure to add the KeyHash for Debug apk or Release apk if you plan to build. May use KeyHash from the PlayStore.

The ListView shows FlatList over ScrollView and avatar rendered on Top right corner along with react-native-floating-action on bottom right corner, which onPress navigates to AddnEdit screen with token and userDetails with setting edit variable to false to make it behave as Add Contact Screen.
The ListView shows FlatList over ScrollView and avatar rendered on Top right corner along with react-native-floating-action on bottom right corner, which onPress navigates to AddnEdit screen with token and userDetails with setting edit variable to false to make it behave as Add Contact Screen.
If valid values are sent by onClick Send button over Add Contact Screen, endpoint is hit with the JWT token and payload and if response is sent back, AddnEdit screen is popped back with the Contact List populated. OnPressing a list key on FlatList , react-native-modal is shown for ContactInfo component is shown with details linking to their placeholders and buttons to edit and delete.
That should help you get started with the repo along with the basic architecture. It does need further implementation of better codebase, security measures and pattern. Do create pull requests and issues.🙏
Any questions? Go ahead and ping me at:
