Gublight

A website helps you explore fantasies on Github.

MIT License

Stars
7
<a href="https://github.com/ericting2000/Gublight/issues">Report Bug</a>

<a href="https://github.com/ericting2000/Gublight/issues">Request Feature</a>

About The Project

Gublight is a React app paid homage to Github in design that could

  • browse users/organizations on GitHub
  • list user's repositories with Infinite Scroll from GitHub REST API
  • get repository's detail from GitHub REST API
  • searching user with Fuzzy Search feature.

Built With

Using

Getting Started

This is how you set up your project locally. To preview online, please visit here.

Prerequisites

  • yarn
    npm install yarn -g
    

Installation

  1. Clone the repo
    git clone https://github.com/ericting2000/Gublight.git
    
  2. Install Yarn packages
  • yarn
    yarn install
    
  1. Start the development server
  • yarn
    yarn dev
    
  1. Enjoy Gublight at http://localhost:3000

Usage

  • Insert the Github user you would like to look for. Options that match your request may show up under the input box.
  • Click 'Explore' or options showed below to navigate to the designated user page. You're welcomed to use the 'Enter' key to submit.
  • In the user's page, all public repository will be listed. Click whichever repo you would like to explore for more information about it.
  • Fill free to re-search for any user at anytime as you wish !

Architecture Design & Explanation

Routing Architecture Diagram

pages
   _app.tsx
   index.tsx	# Landing Page
   400.tsx # Custom 404 page
   500.tsx # Custom 500 page
   users
         [username]
                 repos
                      [reponame].tsx # detailed information of specific repository
                 index.tsx	# List of repositories
  • Dynamic Routing
    • /users/{username}/repos for specific user's repo list.
    • /users/{username}/repos/{repo} for specific repo info of some user.
  • Custom Error Page (404 Not Found, 500 Internal Server Error)
    • Showed when the route is not exist or encounter internal error.

Pages

Landing Page

  • Fuzzy Search
    • Feature is accessible across all app.
    • With Custom Hook useFuzzySearch(), users will be able to implement fuzzy search using the input data they gave to generate suggestions.

Repository List

  • Infinite Scroll

    • Infinite Scroll(Lazy Loading) is essential to this kind of "Large Data requested" app, as it optimizes the performance of both API call procedure and render process.
    • With Infinite Scroll, app only sends a request when the content(data) is about to use. Also, less things for initial render improve the performance and decrease the waiting time which provides a better user experience.
  • How I Implement ?

    • useCallback + useRef() + IntersectionObserver API + useFetchRepoList custom hook.
  • Core Concept

    • When ever the last repository is showed on the screen, we send anthoer request to the API.

    • Below is the example code.

      const { limit, empty, loading, repos, error, hasMore } = useFetchRepo(
        user,
        page
      ); // Fetch or not depends on the value of state "user" or "page"
      const observer = useRef<IntersectionObserver | null>(null);
      const lastRepo = useCallback(
        (node) => {
          if (loading) {
            return; // If is in loading state, return. If it didn't return, fetch function will constantly being triggered due to the observer detection.
          }
          if (observer.current) {
            observer.current.disconnect(); // Disconnect the current observer if is existed.(Which is connected to the previous round's last repo, or "Null" in the first round)
          }
          observer.current = new IntersectionObserver((entries) => {
            if (entries[0].isIntersecting && hasMore) {
              setPage((prevPage: number) => {
                return prevPage + 1; // Entries[0] will be the last repo in current round, which is the one we want to observe. If it exists and it's on the screen, renew the page and triggered fetch function.
              });
            }
          });
          if (node) {
            observer.current.observe(node); // Reconnect observer to the current round's last repo.
          }
        },
        [loading, hasMore]
      );
      
      {
        repos.map((repo: RepoData, index: number) => {
          if (repos.length === index + 1) {
            return (
              // We only want to observe the last repo in every round. Please notice the "ref" property.
              <div ref={lastRepo} key={repo.name}>
                # Code of render repo.
              </div>
            );
          } else {
            return (
              <div key={repo.name} className={styles.repo}>
                # Code of render repo.
              </div>
            );
          }
        });
      }
      
    • For demo, i log a message each time when the fetch funtion is triggerd. Imgur

Repository Information

  • Shows the information of the designated repository.

Components

Header

  • Header.tsx
    • Used all across the app (except for the landing page only), Header.tsx includes the Search Box for users to explore Github.
    • While displayed in mobile mode, the Search Box will folded into the header. (It is still accessible at anytime by clicking the magnifier icon.)
  • LandingHeader.tsx
    • Used only for landing page. No Search Box included.

Footer

  • Footer.tsx
    • Giving a Link for navigation to Gublight's Github repository.

Custom Hooks

  • useFetchRepoList.ts
    • Used for fetching all public repositories that the user has.
    • cooperate with the IntersectionObserver WebAPI to decide whether to fetch for new data or not.
  • useFuzzySearch.ts
    • Used for Fuzzy Search feature.

States Within The Code

  • Error Handling
    • limit for rate limit indication.
    • error for fetching error indication.
    • empty for empty users/repo list/repo info indication.
  • Loading
    • loading for fetching execution.

Other Stuffs

  • Custom Error Page
    • 404.tsx for 404 Not Found
    • 500.tsx for 500 Internal Server Error

A Little More Detail

Rate Limit

  • Github restricts API request to prevent DDoS attack and cyberterrorism. For unauthenticated requests, the rate limit allows for up to 60 requests per hour. Since Gublight is a public repository, we're not allowed to submit personal access token for authentication to increse the limit rate.
  • When you encountered such circumstances, some of the functions may thus be temporarily restricted.

Responsive Web Design

  • With responsive design, Gublight is perfect to use in any of the devices.

  • Toggle the search input by clicking the magnifier icon!

Fuzzy Search Debounce

  • When executing Fuzzy Search, Debounce is necessary to prevent performance issues. Most of the time, chances are the user already have a clue of their search goal. As a result, calling API immediately as soon as the user insert something is not efficent and a wise solution. Also, Debounce largely decrease the probability of hitting the Rate Limit metioned earlier.

    // In useFuzzySearch()
    
    const timeout = useRef<NodeJS.Timeout | null>(null);
    
      useEffect(() => {
        setLoading(true);
    
        function getUserList(queryString: string) {
          clearTimeout(timeout.current as NodeJS.Timeout);
    
          timeout.current = setTimeout(async () => {
            // Fetching data code
          }, 600);
        }
    

SEO

  • SEO(Search Engine Optimization) makes Gublight being found from anywhere at anytime on anydevice all around the world more easily !

    <Head>
      <title>GubLight: Explore the software fantasy</title>
      <meta
        name="description"
        content="Explore the software fantasy. Search the Github Repo as you desire, find the next masterpiece."
      />
      <meta property="og:image" content="https://i.imgur.com/Xf81Hvo.png" />
      <meta name="twitter:card" content="summary_large_image" />
      <meta property="og:type" content="website" />
      <meta property="og:url" content="https://gublight.com" />
      <Favicon />
    </Head>
    

    Adding <Head> seciton to include meta tags and information of Gublight.

License

Gublight is distributed under the MIT License. See LICENSE for more information.