GitHub API Tutorial
GitHub is one of the best ways to collaborate on software and discover new projects using Git, the popular Version Control System (VCS). It's safe to say that GitHub is a huge part of the Open Source Software movement that is continually pushing the bounds of technology as we know it by helping developers contribute to more projects and network with other developers.
GitHub has also created an awesome API for us to build applications with, and the good news is that it's really easy to get started.
fetch
method to send network requests instead of XmlHttpRequest
. If you would prefer to use XmlHttpRequest
please follow the original tutorial here.Using the GitHub API
Let's take a look at how we can start working with GitHub's REST API. Click here for a comprehensive list of available GitHub API endpoints.
For today's example will make use of the GET /users/<username>/repos
endpoint which will allow us to list all public repositories for the specified <username>
parameter. This is a simple API endpoint for us to test the waters with.
In fact, we can actually just paste the url below into a web browser and observe some data đ¤¯.
https://api.github.com/users/timmywheels/repos
If everything went well, you should see the first 30 public repositories for my GitHub username, timmywheels
. If you're feeling daring, try using your GitHub username instead!
GET
request when a URL is entered. Pretty cool!Requesting Resources from GitHub's API Using fetch
There are a number of ways to request data asynchronously from a backend server, but today we'll use the built-in JavaScript fetch
method. As we will soon see, getting started with fetch
is pretty straightforward.
XMLHttpRequest
to request backend resources, but using fetch
is a lot more common.Create a Function to Call GitHub's API
First things first, let's create a simple function that will ultimately wrap the fetch
request to GitHub's /users/<username>/repos
, where <username>
is a dynamic value.
Given that <username>
is dynamic, we'll want to make sure we pass a username
argument to our function.
function requestUserRepos(username){
// we'll fill this in later
}
Use fetch
to request data from GitHub
Let's add our fetch
request to the function we just created above.
function requestUserRepos(username){
// call the fetch method,
// passing in the `username` arg to the request
fetch(`https://api.github.com/users/${username}/repos`);
}
Working with Promises
If you were to invoke requestUserRepos(someUsername)
, you wouldn't see much just yet. That's because when we call fetch
, it returns a Promise
which is...
[an] object [that] represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
Ultimately, a Promise
is a guarantee that an asynchronous operation will complete at some unknown point in the future. Promise
s are particularly useful when dealing with network requests because we don't know when the data will be returned from GitHub (or any API for that matter), but they provide a declaritive way in which our code can handle the various states of a Promise
.
A Promise
will always be in 1 of these 3 states:
pending
: The initial statefulfilled
: The operation was successfulrejected
: The operation failed
Parsing the Promise
returned from fetch
There are a number of ways to leverage Promise
s in JavaScript. We will make use of the Promise.then()
methods which (admittedly) makes the code a little more verbose, but it allows us to work directly from the comfort of our browser console.
async
/ await
syntax as it's more straightforward and easier to read. However, since this is an interactive tutorial designed to be followed through the browser console, I have decided to forgo async/await since this tutorial would largely need to rely on IIFEs (when running in the console)function requestUserRepos(username){
// create a variable to hold the `Promise` returned from `fetch`
return Promise.resolve(fetch(`https://api.github.com/users/${username}/repos`));
}
// call function, passing in any GitHub username as an arg
requestUserRepos('facebook')
// parse response into json
.then(response => response.json())
// log response data
.then(data => console.log(data));
Viewing the Entire API Response
After running the code above, you will see a response that returns an array of 30 objects. Each object contains information about a particular repository. GitHub's API, by default, is set to return the first 30 repos for that particular user in alphabetical order.
You should see something similar to this:
Iterating Through the Payload
Let's say that we wanted to retrieve the name, description, and url for each repo that is returned in the response payload.
You'll notice that if you expand the individual objects from the response payload, they contain all of the information that we're looking for. In our case, we'll want to somehow grab the name
, description
, and html_url
keys from each object within the data
array.
Instead of logging the entire data
payload as we did previously, let's be a little more intentional and log the name
, description
, and html_url
for each individual repository like so:
// call function, passing in any GitHub username as an arg
requestUserRepos('facebook')
// parse response into json
.then(response => response.json())
// iterate through parsed response
.then(data => {
for (let i in data) {
// Log the repo name
console.log('Repo:', data[i].name);
// Log the repo description
console.log('Description:', data[i].description);
// Log the repo url
console.log('URL:', data[i].html_url);
// Add a separator between each repo
console.log('=========================')
}
})
Viewing the Requested API Data đ
Nice! Now we have our GitHub API data formatted into something that's a little easier to read.
So Now What?
Now that we've setup our GitHub API request, we'd naturally want to display this somewhere to the users of our application, and not just in the browser console. So how do we do that?
Creating a Simple GitHub API Example Application
Let's setup a simple project that will display the data of the specified username right on our webpage.
1. Create directory named github-api
on your desktop
Let's create directory on our desktop named github-api
which will hold the files to our simple GitHub API example application.
2. Within github-api
directory, add file index.html
This file will contain the HTML markup for our web app.
3. Within github-api
directory, add file app.js
This file will contain the code we just wrote. We will tweak it along the way to get it to display the requested data on the webpage.
Our index.html
file
This one will be pretty straight forward. Just some simple HTML boilerplate with an h3
, a form
, a ul
, and a link to the app.js
file.
Just to spice things up, we will also import the Bootstrap CSS Library and add a few Bootstrap classes to our HTML elements.
We will use the Bootstrap CSS CDN:
You can find the docs for the CDN here: https://getbootstrap.com/docs/4.1/getting-started/introduction/
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
We will use a few common Bootstrap classes:
I have linked to the corresponding sections of the Bootstrap documentation for each of the classes here.
.text-center
| Used for text alignment | View Documentation.mt-5
,.mx-auto
,.mb-5
,.ml-2
| Used for margins | View Documentation.form-inline
| Used for making form fields inline | View Documentation.form-control
| Used for general appearance of form fields | View Documentation.btn
| Used for general appearance of buttons | View Documentation.btn-primary
| Button appearance modifier class | View Documentation.list-group
| General unordered list styling | View Documentation.list-group-item
| General unordered list item styling | View Documentation
.list-group-item
class is only used in app.js
â not index.html
All in all, there's not much to the Bootstrap classes I've added to this app, however, I wanted to make sure to get you started off on the right track. From here you can certainly put your own spin on things and truly make it your own.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>GitHub API</title>
<!-- Import the Bootstrap CSS CDN -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
</head>
<body>
<h3 class="text-center mt-5">GitHub API</h3>
<form id="gitHubForm" class="form-inline mx-auto" style="width: 280px">
<input id="usernameInput" class="form-control mb-5" type="text" name="username" placeholder="GitHub Username">
<input type="submit" class="btn btn-primary ml-2 mb-5" value="Submit">
</form>
<ul id="userRepos" class="list-group mx-auto mb-5" style="width: 500px">
</ul>
<script src="app.js"></script>
</body>
</html>
Our app.js
file
This will be mostly similar to the code we wrote earlier. The main differences will be that we need to retrieve the user's input from the GitHub username form, and pass that into our requestUserRepos()
function from earlier, then we need to attach the data from our API request to the DOM. We can do this by grabbing on to the ul
with an ID of userRepos
and appending the data as li
's within the ul
all from within the for-loop inside the final .then()
method on requestUserRepos
. Let's give it a shot:
// Get the GitHub username input form
const gitHubForm = document.getElementById('gitHubForm');
// Listen for submissions on GitHub username input form
gitHubForm.addEventListener('submit', (e) => {
// Prevent default form submission action
e.preventDefault();
// Get the GitHub username input field on the DOM
let usernameInput = document.getElementById('usernameInput');
// Get the value of the GitHub username input field
let gitHubUsername = usernameInput.value;
// Run GitHub API function, passing in the GitHub username
requestUserRepos(gitHubUsername)
// resolve promise then parse response into json
.then(response => response.json())
// resolve promise then iterate through json
.then(data => {
// update html with data from github
for (let i in data) {
// Get the ul with id of userRepos
if (data.message === "Not Found") {
let ul = document.getElementById('userRepos');
// Create variable that will create li's to be added to ul
let li = document.createElement('li');
// Add Bootstrap list item class to each li
li.classList.add('list-group-item')
// Create the html markup for each li
li.innerHTML = (`
<p><strong>No account exists with username:</strong> ${gitHubUsername}</p>`);
// Append each li to the ul
ul.appendChild(li);
} else {
let ul = document.getElementById('userRepos');
// Create variable that will create li's to be added to ul
let li = document.createElement('li');
// Add Bootstrap list item class to each li
li.classList.add('list-group-item')
// Create the html markup for each li
li.innerHTML = (`
<p><strong>Repo:</strong> ${data[i].name}</p>
<p><strong>Description:</strong> ${data[i].description}</p>
<p><strong>URL:</strong> <a href="${data[i].html_url}">${data[i].html_url}</a></p>
`);
// Append each li to the ul
ul.appendChild(li);
}
}
})
})
function requestUserRepos(username) {
// create a variable to hold the `Promise` returned from `fetch`
return Promise.resolve(fetch(`https://api.github.com/users/${username}/repos`));
}
Trying Out Our GitHub API App
Now that we've put together all of our code for the front-end markup, our API request, and added some Bootstrap styling - we should be ready to rock.
All you have to do is open up the index.html
file in your browser. On a Mac, you can just double-click the file itself, or right-click > Open With > Google Chrome.
Our Simple App UI
And there it is! Here's what all of our hardworks gone into. This will give you a great framework to build upon and expand your app.
Enter a GitHub Username
Now for the fun part. Enter your GitHub username or even ones like facebook
, airbnb
, reactjs
, or mine - timmywheels
.
Here's the results I got when I plugged in facebook
:
Congratulations, Hacker!
You have successfully built a web application that makes a request to the GitHub API and displays dynamic data to users on the front-end inside the browser! Really cool stuff.
Complete Source Code
Here's a link to the working source code to this tutorial: https://github.com/timmywheels/github-api-tutorial
If you prefer to use the more verbose XmlHttpRequest
, refer to the original
branch of this repo here: https://github.com/timmywheels/github-api-tutorial/tree/original
Stay Tuned đē
If you have any questions or improvements, or if you'd like to see additional examples, feel free to reach out to me anytime at tim@timwheeler.com
. If you're enjoying my posts, please subscribe below! đ