AvidDabbler Blog

GitHub Portfolio Builder

August 16, 2019

The GitHub Portfolio Builder was designed to work with portfolio sites to easily pull down data from your GitHub Repository. My code was designed to easily maintain a portfolio site by pulling directly from your own GitHub reops through the GitHub API as well as using files that are in your repository. The end result is a comprehensive dataset that pulls together:

  • The description that you have associated with a repo on your GitHub
  • The GitHub.com public URL associated with your repo
  • The GitHub API URL that is associated with your repo
  • The URL where you are hosting that GitHub Page
  • A link to a thumbnail photo that you have stored in your root folder of your repo
  • A custom list of technologies that you want to highlight associated with your repo
  • And a commit history for the past year associated with your repo

By the end of this tutorial you will have learned about:

  • Getting your repo setup to work with my default configuration settings.
  • Learn how I structured my code so that you can use it on your own site.
  • An example of how you could incorporate this into your HTML site.

The Layout

In this tutorial we will be restructuring you GitHub repo descriptions to better pull data. There will be 3 different sections:

  • The public name of the repo
  • The public description of the repo
  • and a custom list of technologies that you want to highlight

github descriptions layout

The Code

So before we went any further I thought that it might be nice to go over the logic behind pulling all of the variables and getting them all organized into one object. I have tried to do a good job with writing up good notes within the code that you can take a look at HERE. I will be posting code snippets along the way so that you know explicitly what I am talking about.

Intro

So the way that I structured this is by making some assumptions at the top. The 2 things that are of note at the top are the default username and the description split variables that are set as the default variable if there is nothing listed in the declared variable list further in the code. So what I would recommend is either cloning, forking or copying my repo

To Repo
https://github.com/AvidDabbler/github-portfolio-builder

To Clone
git clone https://github.com/AvidDabbler/github-portfolio-builder.git

Setting Variables

User and Split Variables

In the very top of the code you will find these const variables to set up your username and split variable. Switch out your user name and change the split type if you would like.

//! DEFINING DEFAULTS

const user = `AvidDabbler`; /* ENTER IN GITHUB USERNAME */
const split = ` || `; /*  DEFAULT SEPARATOR */
const finalArr= []; 

So where you see user go ahead an swap out my username for yours and if you want a different split identifier in your description go ahead and set it there.

Selecting Repos

In order for you to pull data you will need to set up your repos that you want to pull from. The code below is a sample of what I have set up to pull data from my repo. In this example there are other variables that I am not taking advantage of. There are a total of 3 variables repo name, user name, and split type. As we went over in the previous section we defined the default user and split at the top of the code, but I wanted to give the option if you had another username.

// * DEFINED REPOS TO DISPLAY
const setupArr = [/* set your variables here. There are 3 variables allowed, 
                    but the last 2 default to the user and split variables 
                    at the top */
    [`backyard-chickens`],
    [`CensusViz`],
    [`dlm-soundboard`],

];

Code Rundown

getData()

The following code snippet shows the full process of getting the data out of GitHub. This process is run through a for loop in the reposFunction() which we will cover in the next section.

const getData = async(i, repo, usr = user, splt = split)=>{
    const gitLink = `https://api.github.com/repos/${usr}/${repo}`;
    const fetchedData = fetch(gitLink)
        .then(response=> response.json())
        .then(myJson=> ({data:myJson}))
        .then(res =>{return res.data.description});
    const object = await fetchedData;
    const objArr = object.split(splt);

    const statLink = `https://api.github.com/repos/${user}/${repo}/stats/participation`;
    const statData = fetch(statLink).then( response=> 
        response.json()).then(myJson=> ({
            data:myJson
        })
        ).then(async res =>{
            return res.data.all
        });

    /* FINAL PRODUCTS */
    const formTitle = objArr[0];
    const description = objArr[1];
    const technology = objArr[2].split(', ');
    const particData = await statData;


    return {
            id: i,
            repo: repo,
            gitUrl: `https://github.com/${usr}/${repo}`,
            thumbnail: `https://raw.githubusercontent.com/${usr}/${repo}/master/thumbnail.png`,
            homepage: `https://${usr}.github.io/${repo}/`,
            apiUrl: gitLink,
            title: await formTitle,
            descr: await description,
            tech: await technology,
            stats: await particData
            }
        };

variables

In the first line of this code you are linking to your setupArr as well as the default or defined 2nd and 3rd variables in the setupArr. These variables are then used to parse through the section and pull together the GitHup URL’s that you will need to build your json objects at the end that will build your site.

const gitLink = `https://api.github.com/repos/${usr}/${repo}`;
    const fetchedData = fetch(gitLink)
        .then(response=> response.json())
        .then(myJson=> ({data:myJson}))
        .then(res =>{return res.data.description});
    const object = await fetchedData;
    const objArr = object.split(splt)

The section above is the section that took me the most time to pull together. This is how we are able to fetch the raw data, then turn it into json, then go into the data key and return description. Which is what you will be formatting in all of your repositories on the front page of your repos. Using const object you await the data then you use that response to split out the data into an array. Scrolling down a bit you will find the const technology variable. This variable will use the result that you just produced.

const technology = objArr[2].split(', ');

To get back the commit history information you need to go to the stats API that GitHub has. The const statsLink is what is used to route specifically to the data concerning the amount of participation has taken place on each of the repos that you are querying. In const statsData it then takes that URL that you generated and then pulls the data from that location, converts that data to json. Then later in the code that code the resolved promise data is then stored in a static variable const particData.

const statLink = `https://api.github.com/repos/${user}/${repo}/stats/participation`;
    const statData = fetch(statLink).then( response=> 
        response.json()).then(myJson=> ({
            data:myJson
        })
        ).then(async res =>{
            return res.data.all
        });

… later in the code

const particData = await statData;

reposFuntion()

So the getData() will work if you have just one reop object, but if you have multiple reops that you are wanting to stor in a object you will need to use the reposFunction(). This function will call getData() for each item in setupArr and cycle through the list of repos that you have set up in the setupArr.

const reposFunction = async () => { 
    for(let i = 0; i < setupArr.length; i++){
        let el = setupArr[i];
        const getDataObj = await getData(i, el[0], el[1], el[2]);/* el 2 and 3 are optional */
        finalArr.push(getDataObj);
    };
};

The Setup

Description & Technology Formatting

The description can easily be set up by going to your repo and clicking edit at the top of the page next to the repo description. As I mentioned earlier the repo description is broken out into 3 sections:

  • Public Name
  • Description
  • Technology

Feel free to set them up with whatever you like while remembering to include your custom separator. For the technology section make sure to separate them out by using a comma in the third section.

github descriptions layout

Thumbnails

This project has been configured to have the thumbnail photo located in the master root folder of your repo called “thumbnail.png”. Location can be edited by going in the getData() return function and changing up the thumbnail template literal.

thumbnail in repo

thumbnail: `https://raw.githubusercontent.com/${usr}/${repo}/master/thumbnail.png`;

IMPORTANT: This url will be case sensitive

Deployment

Now all of that is well and good, but now we are going to talk about how to get it to work within an HTML site. Using portfGen(). This function within my code is running everything. It is running my reposFunction() (which runs getData()). This function will iterate through all of the json objects that I have created and stored in the finalArr. The if statement within the function is just there for rendering either on the left or the right side of the screen based on the i from when we ran getData().

// * GITHUB DATA RENDERING
const portfGen= async()=>{ 
    await reposFunction();
    
    const data = await finalArr;
    for(let i=0; i < data.length; i++){
        if(i % 2 == 0){
            document.getElementById("portfolio-content").innerHTML+=
             `<div id="project-${i}" class="portfolio-container content">
                <div class="thumbnail"><a href="${data[i].homepage}" target="_blank">
                <img class="" src="${data[i].thumbnail}" alt="${data[i].title} application photo"></img></a></div> 
                <div class="paragraph">
                    <h2>${data[i].title}</h2>
                    <p>${data[i].descr}</p>
                </div>
            </div>`
        }
        else{
            document.getElementById("portfolio-content").innerHTML+= 
            `<div id="project-${i}" class="portfolio-container content">
                <div class="paragraph">
                    <h2>${data[i].title}</h2>
                    <p>${data[i].descr}</p>
                </div>
                    <div class="thumbnail"><a href="${data[i].homepage}" target="_blank"><img class="" src="${data[i].thumbnail}" alt="${data[i].title} application photo"></img></a>
                </div>`
        }
    }
}

Implementations

I have implemented this GitHub code to build my own personal portfolio site so that I can easily update this information when I know someone is going to be looking at my site.

Check it out @ walterkjenkins.com


Written by Walter Jenkins who lives and works in Saint Louis. His passions are Civic Tech, Smart Cities and Alternative Transportation. He specializes in working with data analysis and visualization through maps.
You should follow him on Twitter.