Building a Github Profile App using ReactJS
Tags: javascript, react, styledcomponents, css
Published: 2023-01-07 12:52:36

This was a project built as part of my second semester exams at [AltSchoolAfrica](https://www.altschoolafrica.com/). 

## Introduction
The task was to build a ReactJS app that fetches my Github portfolio with the following key functionalities

- Show a page with a list of all my repositories on Github
- Show another page linking to each repositories using nested routes while using all the necessary tools in React.
- Implement proper SEO (Search Engine Optimisation)
- Implement Error Boundary functionalities
- Add a 404 page.

You can find the source code on [Github](https://github.com/kuicpet/github_user_profile) and app was hosted on [here](https://github-kuicpet.vercel.app/)

Lets go through the steps I followed in creating this project.

## ReactJS
ReactJS is an open-source JavaScript library for building user interfaces and creating interactive web applications. React is primarily used for building single-page applications and mobile applications. It uses a declarative, component-based approach to making user interfaces, which makes it easier to build and maintain complex user interfaces. React also makes it easier to create reusable components that can be used across different applications.

## Scaffolding the app
The first step was to scaffold the react app using [create-react-app](https://create-react-app.dev/) using `npx create-react-app github_profile` on my terminal after which I changed directory into the project folder and on the terminal ran the command `yarn start` to start the development server on `http://localhost:3000`




![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jn9k8ki8tmh2wd5vpwa2.png)

**NPM (Node Package Manager) Dependencies**
The next step was installing the npm dependencies by running the command on the terminal 
`yarn add react-router-dom styled-components react-icons react-helmet react-error-boundary moment`

**App Folder Structure**
The next step was creating sub-folders inside the `src` folder 
namely `assets components hooks pages`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hhcbhjznztzosyvpsuqm.png)

The `assets` folder to hold image assets, the `components` folder to hold reusable components, the `hooks` folder to hold logic for api calls and the `pages` folder to hold different pages.

## Continuous Integration and Continuous Development (CI/CD)
I created the project repository on [Github](https://github.com), and using the command line on my  terminal pushed the code to github to save and track changes and updates during development.
I also setup the app to be hosted on [Vercel](http://vercel.com/), this to make me see the changes both on my local machine and on a hosted link.

## Building the app
**Components**
After creating the needed app folder structure,next was to create the reusable components in the components folder as shown in the image below
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/earvuqrhahcgwtba3saw.png)
I added an `index.js` file to export the components from components folder to make my code cleaner when importing these components.

```
import Button from './Button'
import Card from './Card'
import Header from './Header'
import Footer from './Footer'
import Loader from './Loader'
import SearchBar from './SearchBar'
import Grid from './Grid'
import Meta from './Meta'
import BreadCrumb from './BreadCrumb'
import Paginate from './Paginate'
import Card2 from './Card2'

export {
  Button,
  Card,
  Header,
  Footer,
  Loader,
  SearchBar,
  Grid,
  Meta,
  BreadCrumb,
  Paginate,
  Card2
}
```
To see the detailed code for each component, please check out the [repository](https://github.com/kuicpet/github_user_profile)
**API**
Briefly an API (Application Programming Interface) is an interface or set of protocols that provides a way for different applications to interact with each other. An API can allow two applications to communicate with each other and exchange data, making it easier for developers to create applications that work with other applications. APIs can also be used to access data stored in databases or other services.
For this app I made use of the [Github api](https://docs.github.com/en/rest?apiVersion=2022-11-28), and then obtained an access token from Github to enable me interact with the api from the react app, please make sure your access token is saved in an `.env file` and the environment file `.env` added to the `.gitignore file` to prevent exposing your access token on github

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hflrffs6r9g6fmdvu2sx.png)
**Custom hooks**
Next I created custom hooks inside the hooks folder for interacting with the api and making api calls from the Github api endpoints, As seen in the image below, I created 3 custom hooks, `useApiFetch.js` to fetch my github repositories, `useProfileFetch.js` to fetch my github profile and `useRepoFetch` to fetch a single repository using the `repoId`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0zabc0j96nnffnk662iy.png)
To see the detailed code for each custom hook, please check out the [repository](https://github.com/kuicpet/github_user_profile)

**Pages**
Next was to create the different pages namely `Home, NotFound (404),Error, Repos, SingleRepo, SearchResults`, inside the pages folder as shown in the image below
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6z6ocwucdjwsn7y47vi8.png)
**Routing and Error Boundary implementation**
Routing was implemented using `react-router-dom`,while Error boundary was implemented using `react-error-boundary`,  both are npm packages for react. The routes created were for the different pages, below is the code for the routing and error-boundary 

```
Index.js file
import React from 'react'
import ReactDOM from 'react-dom/client'
import { ErrorBoundary } from 'react-error-boundary'
import { BrowserRouter as Router } from 'react-router-dom'
import './index.css'
import App from './App'
import reportWebVitals from './reportWebVitals'
import styled from 'styled-components'


const ErrorFallback = ({ error }) => {
  return (
    <Container>
      <Content>
        <p>Something went wrong</p>
        <pre>{error.message}</pre>
      </Content>
    </Container>
  )
}

export const Container = styled.section`
  display: flex;
  flex-direction: column;
  width: 100%;
  align-items: center;
  justify-content: center;
  min-height: 75vh;
`
export const Content = styled.div`
  p {
    font-size: 1.5rem;
    font-weight: 200;
    text-align: center;
    color: black;
    margin: 0.5rem 0;
    //width: 50% ;
    @media screen and (max-width: 400px) {
      font-size: 2rem;
    }
  }
  pre {
    color: red;
    width: 50%;
    text-align: center;
  }
`

const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  <React.StrictMode>
    <Router>
      <ErrorBoundary FallbackComponent={ErrorFallback}>
        <App />
      </ErrorBoundary>
    </Router>
  </React.StrictMode>
)

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals()

```

```
App.js file
import React from 'react'
import { Route, Routes } from 'react-router-dom'
import { Footer, Header } from './components'
import Home from './pages/Home'
import Repos from './pages/Repos'
import SingleRepo from './pages/SingleRepo'
import NotFound from './pages/NotFound'
import styled from 'styled-components'
import SearchResults from './pages/SearchResults'

const App = () => {
  return (
    <Container>
      <Header />
      <Routes>
        <Route exact path='/' element={<Home />} />
        <Route exact path='/search/:keyword' element={<SearchResults />} />
        <Route exact path='/repos' element={<Repos />} />
        <Route exact path='/repos/:repoId' element={<SingleRepo />} />
        <Route path='*' element={<NotFound />} />
      </Routes>
      <Footer />
    </Container>
  )
}

export const Container = styled.div`
background-color: rgba(255, 255, 255, 0.16);
`

export default App

```
**Styling**
For styling, I used styled-components in writing the css for each components and pages,as this saves me time editing bulky, clumsy, and sometimes complex CSS files as the app grows bigger with additional features.

**Additional Features**
In addition to the basic functionality of fetching my Github repositories,and view the individual repository details, I added  
- Search Functionality, where you can search for any Github user by their username, 
- A Search Results page for displaying the searched Github user profile details.
- Pagination Functionality, to make it easier to view my repositories which enhances the user experience as they don't have to scroll all the way down to view more repositories.

**Recent Improvements**
I recently updated some features to improve the User experience
- on mobile devices, the font weight was increased to make the descriptions on the repository cards more readable.
- I added a skeleton loading state, to give user feedback as app is loading using the `react-loading-skeleton npm package`.

**Future Additional Features**
I am hoping to add other features to this app in future, such as 
- Authentication Functionality, where a user can sign up and login to view their Github Repositories
- Improve the user interface (UI) and enhance the user experience (UX)

If there is a feature you would like to see, please let me know by adding a comment to this article, thanks.

You can find the source code on [Github](https://github.com/kuicpet/github_user_profile)