This article was originally posted on Medium. If you prefer reading it from there, please do check it out.
Introduction
With the advent of countless templates and web page design applications, the task of creating a personal portfolio transitioned from a painful endeavor into a painless task.
However, the act of constantly updating the hard-coded information and rebuilding and redeploying your portfolio turns into a tiresome burden.
In this tutorial, I will show you how I integrated the Github API into my portfolio to pull the most recent project information, solving the issue of directly updating and redeploying my portfolio.
Agenda
Setup
Service
Integrate
Setup
Before we build the solution, let’s first understand the core idea and configure Github to ease the integration.
First, let’s talk about the Github repositories. To elaborate, I house my projects in the repositories themselves: I host the source code, keep detailed descriptions, and maintain links to demo gifs or images.
This repository houses my Path Finding Visualizer project.
In the right side, the section outlined in blue contains the description of the project. On the other hand, the section outlined in red has a link to the demo. Finally, the section outlined in black contains topics associated with the project.
To sum it all up, the Github API will return the above fields upon an HTTP request to:
GET /users/{username}/repos
This endpoint will return a list of public repositories for a user.
Here is what the return json object looks likes for the Path Finding Visualizer repository.
Although it is a bit difficult to see, the API returned the fields we need: description, homepage, and topics.
This is fantastic news, since it shows that we can store and retrieve information from our repositories.
Let’s now work on configuring Github to simplify the integration.
All we need to do is generate a personal access token in the developer settings. We will use the personal access token to authenticate our requests to the Github API so we can take advantage of the generous rate limits.
First, navigate to your profile settings.
From your profile settings, navigate to the developer settings.
Finally, go to the personal access tokens tab.
At this point, you can click “Generate new token” and Github will walk you through the rest. Once you have generated the token, make sure you save it to the clipboard, since we will need it for later.
Now that we have generated our personal access token, we can work on the actual integration.
Service
To start, let’s conceptualize how the portfolio would interact with the Github API.
Building a separate service that communicates between the portfolio and the Github API is a good idea, since we should house our Github personal access token in a secure environment.
Here is a depiction of the network flow:
Let’s start building out the service.
I will be using Python and Flask, but just understand that you can use any stack of your choice.
First, let’s create a config.py
file. In this file, we will store our Github username and our personal access token. Make sure you do not push this file to version control.
USERNAME = "YOUR GITHUB USERNAME"
TOKEN = "YOUR PERSONAL ACCESS TOKEN FROM EARLIER"
Let’s create a server.py
file and make a simple Flask app.
from flask import *
from flask_cors import CORS
from config import *
app = Flask(__name__)
CORS(app)
if __name__ == "__main__":
app.run()
Now, let’s expose an endpoint that our portfolio can call to get the project data.
@app.route("/projects", methods=["GET"])
def getProjects():
pass
The getProjects()
method will do three things.
It will make a request to the Github API for the repository data.
It will extract the relevant fields from each of the repositories.
It will return the filtered data back to the portfolio.
Let’s tackle these steps one by one.
Making a request to Github
We can simply use the Python requests library to make the HTTP request.
url = "https://api.github.com/users/USERNAME/repos"
headers = {"Accept":"application/vnd.github.mercy-preview+json"}
repos = requests.get(url, headers=headers, auth=(USERNAME,TOKEN)).json()
The Github API will also include the topics
field for each of the repositories if we pass in the above headers.
If all goes correctly, the request should have a status of 200 and the repos
variable should be a list of json objects.
Extracting relevant fields
The main fields of concern are id
, name
, html_url
, description
, topics
, and homepage
. The homepage
field represents the text stored in the black outlined area:
We can put links to our demo gifs in homepage
.
The code to parse each of the repositories is this:
projects = []
for repo in repos:
if repo["homepage"]:
project = {
"id": repo["id"],
"name": repo["name"],
"url": repo["html_url"],
"description": repo["description"],
"topics":repo["topics"],
"images": repo["homepage"].split(";")
}
projects.append(project)
Just to clarify, I added more than one demo link for certain projects. I separated each link with a semi-colon.
Here is what project
would look like for the Path Finding Visualizer repository:
{
"id": 206887035,
"name": "Pathfinding-Visualizer",
"url": "https://github.com/Ramko9999/Pathfinding-Visualizer",
"description": "Built a colorful visualizer for shortest path algorithms: A star search, Breadth First Search, and Bidirectional Breadth First Search. Utilized Queues and Priority Queues to reduce collection operations such as pop() and push() to O(1) and O(log(n)) run times.",
"topics": [
"data-structures",
"graph-algorithms",
"java",
"pathfinding",
"swing"],
"images": [
"https://media.giphy.com/media/U6GuVGBOQoHUHaZ7LV/giphy.gif",
"https://media.giphy.com/media/gg9eCb2ZBqcU4LlSML/giphy.gif",
"https://media.giphy.com/media/l4Wyj6PQwwxZdPjfSe/giphy.gif",
"https://media.giphy.com/media/LRgBCMGhCvqkzHzeaY/giphy.gif"]},
All that remains now is to return projects
back to the initiator of the request.
Returning a response
We can return the filtered data back to the client with the following:
return {"projects": projects, "error": False}
So with all the pieces put together, the getProjects()
method will look as such:
Please be sure to test your service locally by calling the /projects
endpoint. Once it is working, you can deploy it wherever you like. Personally, I deployed the service on pythonanywhere.com.
Pat yourself on the back, as the hardest part is now over!
Integrate
All that remains now is that we have to make an HTTP request from our portfolio website to the service we have just created.
For example, I used React to build out my portfolio, so here is how I made the call and fetched the projects.
All you need to do now is to build out the user interface based on the data.
With that said, feel free to head over to my portfolio to check out how I implemented my user interface.
That's it folks!
Top comments (0)