Build Your Own Puppy Playdate Tinder App with Slash GraphQL
Tags: react, javascript, graphql, dgraph
Published: 2020-12-14 12:50:36

Every dog owner wants to find the perfect friends for their new puppy. Now we have an app for that! You can browse through various puppy profiles and swipe right or left to find your new puppy friend. Setting up puppy playdates has never been easier!

Ok, not really... But we do have a wacky demo app built with [React](https://reactjs.org/), [Material-UI](https://material-ui.com/), [Apollo Client](https://www.apollographql.com/docs/react/), and [Slash GraphQL](https://dgraph.io/cloud/) (a hosted GraphQL backend from [Dgraph](https://dgraph.io/)).

In this article we'll explore how I built the app and also look at some of the basics of the technologies I used.

Ready to *unleash* the fun?

*Update: On April 16th, 2021, Slash GraphQL was officially renamed Dgraph Cloud. The information below still applies, and you can still build the app as described.*

---

## Overview of the Demo App

![Puppy playdate app](https://dev-to-uploads.s3.amazonaws.com/i/lhy2flc0v98sxu030776.png)
<figcaption>Puppy playdate app</figcaption>

Our app is a Tinder clone for puppy playdates. You can view our puppy profiles, which are pre-generated seed data I included in the database. You can reject a puppy by swiping left or by clicking the X button. You can show interest in a puppy by swiping right or by clicking the heart button.

After swiping left or right on all the puppies, your results are shown. If you're lucky, you'll have matched with a puppy and will be well on your way to setting up your next puppy playdate!

Check out the [demo app here](http://tylerhawkins.info/puppy-playdate/build/)! You can also [see the code on GitHub](https://github.com/thawkin3/puppy-playdate).

In this article we'll walk through setting up the schema for our app and populating the database with seed data. We'll also examine how the puppy profiles are fetched and how the match updates are done.

---

## The Architecture

As noted above, the four core technologies behind this app are  [React](https://reactjs.org/), [Material-UI](https://material-ui.com/), [Apollo Client](https://www.apollographql.com/docs/react/), and [Slash GraphQL](https://dgraph.io/cloud/).

I chose React because it's an excellent frontend library for developing UIs in a declarative way with reusable components.

Material-UI helped provide the building blocks for the UI components. For example, I used their `Button`, `Card`, `CircularProgress`, `FloatingActionButton`, and `Typography` components along with a couple icons so that I had some base component layouts and styles to use as a starting point.

I used Apollo Client for React to facilitate communication between my frontend components and my backend database. Apollo Client makes it easy to execute queries and mutations using GraphQL in a declarative way, and it also helps handle loading and error states when making API requests.

Finally, Slash GraphQL is the hosted GraphQL backend which stores my puppy data in the database and provides an API endpoint for me to query my database. Having a managed backend means I don't need to have my own server up and running on my own machine, I don't need to handle database upgrades or security maintenance, and I don't need to write any API endpoints. As a frontend developer, this makes my life a lot easier.

---

## Getting Started with Slash GraphQL

Let's first walk through creating a Slash GraphQL account, a new backend, and a schema.

You can [create a new account](https://cloud.dgraph.io/) or log in to your existing Slash GraphQL account online. Once authenticated, you can click the "Launch new backend" button to view the setup screen shown below.

![Creating a new backend with Slash GraphQL](https://dev-to-uploads.s3.amazonaws.com/i/c2vql1wdse96ktvuno0w.png)
<figcaption>Creating a new backend with Slash GraphQL</figcaption>

Next, choose your backend's **name** ("puppy-playdate" in my case), **subdomain** ("puppy-playdate" again for me), **provider** (AWS only, currently), and **zone** (choose one closest to you or your user base, ideally). When it comes to pricing, there's a generous free tier that's enough for this app.

Click the "Launch" button to confirm your settings, and in a few seconds you'll have a new backend up and running!

Once the backend is created, the next step is to specify a schema. This outlines the data types that your GraphQL database will contain. In our case, the schema looks like this:

{% gist https://gist.github.com/thawkin3/720ca53a2f0f4a1d799fcb801e46164c %}
<figcaption>GraphQL schema for our database</figcaption>

Here we have defined a `Puppy` type that has the following fields:

- `id`, which is a unique ID generated by Slash GraphQL for each object stored in the database
- `name`, which is a string of text that is also searchable
- `age`, which is an integer
- `matchedCount`, which is also an integer and will represent the number of times a puppy has matched with someone
- `profilePic`, which is a string that contains the image url to be shown in the app
- `bio`, which is a string that contains a short description about the puppy
- `interests`, which is an array of strings representing the puppy's interests and is also searchable

---

## Adding Puppies

Now that we have a backend endpoint and schema set up, it's time to add some puppies! The API Explorer in the Slash GraphQL web console allows us to easily execute GraphQL queries and mutations against our database without having to write or run any additional code within our app. We'll insert data into the database using this mutation:

{% gist https://gist.github.com/thawkin3/ba2651a2a22268bf1fb106501b1fa6b8 %}
<figcaption>Mutation to add all puppies to the database</figcaption>

We can then query our database to fetch the puppy data as a quick sanity check that our seed data was inserted properly. The query looks like this:

{% gist https://gist.github.com/thawkin3/3fa8aeceee57e1a890110e154b051d38 %}
<figcaption>Query to get all puppies from the database</figcaption>

The data is then shown in the API Explorer's results panel like so:

![Querying the database for all our puppies](https://dev-to-uploads.s3.amazonaws.com/i/0r6oefknv8667g3mwfms.png)
<figcaption>Querying the database for all our puppies</figcaption>

---

## Fetching Puppies (ha…)

Now that we have our database populated with seed data, we can work on getting our puppies to show up in our app. I used [React](https://reactjs.org/) to build the UI and [Material-UI](https://material-ui.com/) for my component library to help speed up the development process. Rather than executing GraphQL queries and mutations directly, I chose to use [Apollo Client for React](https://www.apollographql.com/docs/react/) to declaratively handle interacting with my backend API and database.

Apollo Client utilizes [React's Context API](https://reactjs.org/docs/context.html). To get started, you first initialize a new client and then wrap your root component with a provider component. This makes the database data available anywhere in the app through the context.

{% gist https://gist.github.com/thawkin3/0a52f1054e66f2295acb7520c6d89a49 %}
<figcaption>Creating a new Apollo client</figcaption>

{% gist https://gist.github.com/thawkin3/948ce9fe6379d02ecd894ab2cdb076f2 %}
<figcaption>Wrapping the app in the Apollo provider component</figcaption>

Then in our `App.js` file we can define a GraphQL query to fetch all the puppies:

{% gist https://gist.github.com/thawkin3/10ff859c9dc8d194830df67e2ba12c0b %}
<figcaption>GraphQL query to fetch all puppies</figcaption>

We then declaratively execute the query inside our `App` component and work with the response data by using Apollo Client's `useQuery` hook:

{% gist https://gist.github.com/thawkin3/38c1c5f6b5b7c56264108b95f99cea92 %}
<figcaption>Executing the query with the useQuery hook</figcaption>

The result of calling that method is an object which contains properties for the response `data`, `loading` state, `error` info, and a method to `refetch` the data. We only need access to the `data` property and the `refetch` method, so we destructure those two items from the object and then pass them down into child components as needed.

![Welcome screen in the puppy playdate app](https://dev-to-uploads.s3.amazonaws.com/i/i15tw3g6tseicbjb3efn.png)
<figcaption>Welcome screen in the puppy playdate app</figcaption>

![Loading screen in the puppy playdate app as the puppy data is being fetched](https://dev-to-uploads.s3.amazonaws.com/i/5qj266lv1njsonsfs2c4.png)
<figcaption>Loading screen in the puppy playdate app as the puppy data is being fetched</figcaption>

---

## Updating Puppy (Love)

Once the puppy data is fetched, the puppies are shown one by one as interactive cards. The "Tinder swipe" effect is implemented using an npm package called [react-tinder-card](https://www.npmjs.com/package/react-tinder-card).

When a puppy card is swiped to the right (or when the heart button is clicked), an API request is made to the backend to increment the puppy's `matchedCount` value by one. This is done through Apollo Client again, but this time using the `useMutation` hook since this is a GraphQL mutation.

Just as before, we first write our GraphQL mutation:

{% gist https://gist.github.com/thawkin3/f97ecacb9694afa1cfefd53a7b8829cc %}
<figcaption>GraphQL mutation to update a puppy's data</figcaption>

Then we execute the mutation inside our component, this time as part of our swipe event handler method called `swiped`:

{% gist https://gist.github.com/thawkin3/77e5ea5ff256d4159fe5a04a5a559a03 %}
<figcaption>Executing the mutation with the useMutation hook and swiped event handler</figcaption>

![Doug is a good boy](https://dev-to-uploads.s3.amazonaws.com/i/5pukdzxvcx1iodoq2zjn.png)
<figcaption>Doug is a good boy</figcaption>

Each liked dog is recorded. Once you've swiped through all eleven dogs in our database, your match results are shown!

![You matched with Louie!](https://dev-to-uploads.s3.amazonaws.com/i/qjsn4ip0dm5c13bpqnfu.png)
<figcaption>You matched with Louie!</figcaption>

---

## Next Steps

That's it for our demo app! If you as the reader wanted to continue to build on this project, you could extend the app by creating an [authentication](https://dgraph.io/docs/graphql/authorization/authorization-overview/) workflow and allowing users to create accounts and post their own profiles. You could also allow users to actually match each other and send them notifications when that happens.

---

## Wrapping Up

As I built this app and considered the features and functionalities I wanted to include, the database schema changed over time. I started without including the puppies' ages or their interests. When I decided that I did want to show that info on the puppy cards, I simply edited my schema in the Slash GraphQL web console to include the `age` and `interests` fields.

I also originally started with a Boolean `matched` field to show whether or not you were matched with each puppy. However, since this app includes no authentication and can be used by any user, it felt more appropriate to instead use a `matchedCount` field that recorded how many times each puppy had previously been "liked" by any user. Making this tweak to the schema was again as simple as replacing the `matched` Boolean type with the `matchedCount` Int type.

The flexibility of GraphQL in allowing me to edit my schema on the fly without having to rewrite several API endpoints greatly sped up the development process. And Slash GraphQL's API Explorer allowed me to easily execute queries and mutations directly against my database to experiment with the syntax and the fields I'd need before having to write any app code.

The architecture I chose was perfect for developing this app  –  it made rapid prototyping easy! The *paw-sibilities* are endless!

---

*Update - January 20, 2021*: This article mentions a Slash GraphQL free tier. Dgraph recently updated their pricing model for Slash GraphQL. It’s now $9.99/month for 5GB of data transfer. No hidden costs. No costs for data storage. No cost per query. You can find [more info here](https://dgraph.io/pricing/).