Skip to content

Gearbox Getting Started

Theo G edited this page Dec 7, 2023 · 6 revisions

Gearbox Dev Getting Started


Theo Gillespie - Nov 30th, 2023

Howdy, Let's Get Right To It

In this tutorial, you will learn how to become a master in the mysterious ways of Gearbox (SJ3).

We will begin by installing Gearbox locally on your machine, and getting it running correctly. Then we will implement our own web page from scratch using Gearbox's internal libraries.

This tutorial assumes you have basic knowledge of NodeJS/TypeScript, HTML, CSS, and React. Each one of these prerequisites has easy and accessible online guides if you need to learn these core components of web development.

This tutorial is also much easier if you use VS Code, and there are even several extensions that can make your life even easier such as Tailwind Support

Installation

Gearbox

To begin, copy the most recent build of Gearbox at https://github.com/Decatur-High-GlobalDynamics/Gearbox/releases. This guide is written for the v0.0.1 release, and has been tested to make sure there are not any issues 😃.

NodeJS

Gearbox runs in a NodeJS local environment (which is essentially a method of running JavaScript locally on a computer, instead of in a browser). There is a decent chance NodeJS is already installed on your machine, but if it is not, then install the latest LTS version here: https://nodejs.org/en/download

MongoDB

Gearbox uses MongoDB as the core database for its operation, which is an external software. For local testing, it is possible to use MongoDB's online service Atlas (https://www.mongodb.com/atlas/database) which allows you to create a free personal database in the cloud.

Personally, I prefer installing MongoDB locally on my machine and using the included tool MongoDB Compass which is a GUI that allows you to easily manually navigate and edit the database yourself- however using Atlas is entirely compatible and frankly easier.

You can download MongoDB here: https://www.mongodb.com/try/download/community

Setup

Once everything is installed, open the downloaded repository in VS Code. In the terminal, ensure you are in the Gearbox directory and then run:

npm ci

This command will install all of Gearbox's dependencies and packages. This is required for Gearbox to operate correctly. It might take a while for all the packages to install, but once they are all downloaded, we are ready to move on the next step.

Configuring Gearbox

Gearbox is configured by settings and strings that are loaded from a private .env file. Most values present are fairly self-explanatory, but you can see the definitions of these values in enviroment.d.ts.

This file is not included by default in the Gearbox repository, as it exposes clear-text API keys and security codes, however, we can make our own very quickly.

/.env

NEXTAUTH_URL=https://localhost:3000/
NEXTAUTH_SECRET=theoissuperawesome
GOOGLE_ID=[create a Google oauth key and put it here]
GOOGLE_SECRET=[create a Google oauth key and put it here]

MONGODB_URI=mongodb://localhost:27017
DB=demo

TBA_URL=https://www.thebluealliance.com/api/v3
TBA_KEY=[create a TBA API key]

API_URL=/api/
API_KEY=gearboxiscool

FILL_TEAMS=true

DEFAULT_IMAGE=/user.jpgcd 

Initializing Gearbox

Gearbox is a NextJS based project. NextJS is a React framework that supports many features such as handling React in webpages, managing data and routing. NextJS is special as it is a popular full-stack framework which means that it allows us to code webpages (client-side) and server-side functions all in one place. It additionally supports many features such as Server-side Rendering and integrated data fetching which means that it works super duper fast.

To operate a NextJS project, we use these three core commands:

  • npm run dev - Starts a local development server with Fast Refresh
  • npm run build - Creates an optimized production build of the project
  • npm run start - Starts the production build of your code

For running our local development build, run npm run dev. As your first time initializing the code, it may take a minute for the entire project to fully boot. Once everything is configured, you can see the code running live at https://localhost:3000.

Now you can explore Gearbox just like it is online!

As you may notice, the pages might load a bit slower than normal- this is expected because the server and pages are constantly recompiled in order to show your latest changes.

Creating A Custom Page

Now that we have Gearbox running, we can begin contributing and in particular, adding a new page. For this example, we will create a page that shows all of Gearbox's Teams, plus statistics, on one central page.

Let's begin first by looking over how the project is structured. Everything in Gearbox rests inside their respective directories:

/certs - holds the official HTTPS certifications
/components - holds reusable React components (not really implemented)
/lib - holds internal specific server-side code for Gearbox (ex: API and DB functions)
/lib/client - holds client-specific functions (ex: API, WebSockets)
/lib/dev - holds code for development features (ex: fake-user generation)
/pages - holds the actual web pages of Gearbox, split into sub-directories according to the SLUG (Short URL) pattern
/public - holds hosted content resources
/styles - holds CSS files- as we use Tailwind it is not used outside of global fonts/settings

To begin lets create a new page in /pages, lets name it something obvious like teamOverview.tsx. We can fill this file initially with some general boilerplate code. Included are comments that have some explanation for each piece's function.

import { Team } from "@/lib/Types"; // Imports the Team type
import { useEffect, useState } from "react" // Imports basic functions from react

import { useCurrentSession } from "@/lib/client/useCurrentSession"; // imports a method for getting the user's current auth

import ClientAPI from "@/lib/client/ClientAPI"; // imports the client-side API
import Container from "@/components/Container"; // imports the container react component (which contains the nav-bar, auth verification, and header)

const api = new ClientAPI("gearboxiscool"); // create an instance of the client-side API, gearboxiscool is the private auth key

export default function TeamOverview() { // declare our react component

    const { session, status } = useCurrentSession(); // fetch your current session

    return <Container requireAuthentication={true} hideMenu={false}></Container> // create the barebones web page
}

As we can see, the contents here are pretty self-explanatory and really work to show how simple the internals of Gearbox are. To actually add some functionality, we need to get data. To do this, lets update our component with a couple of things.

First lets add a state to keep track of our data fetching. We can use this later to show whether the page is loading later. We can also have a state to hold our future data (an array of Teams)

const[loading, setLoading] = useState(false);
const[teams, setTeams] = useState<Team[]>([]);

Now we can begin with our data fetching. To do this, we are going to add a useEffect clause that calls an asynchronous function to our component. We will define this function in a second.

useEffect(() => {

  fetchData();
}, []);

This ensures that whenever the component resets, we fetch data from the server using our function.

Note: React does not support async/await in hooks, which means we have to call them outside of the hook or in a useCallback function

Now we can define our function that actually uses our API to fetch data from the server and the database. The majority of the operations in Gearbox are structured similarly to this way.

const fetchData = async () => {
        setLoading(true); // set the fetching process
        const teamData: Team[] = await api.allTeams() // specific API path that gets every team in the database
        setTeams(teamData);
        setLoading(false); // all done!
}

Now this means we have cached data that is fetched from our server. Now we can actually work to display this data.

Note: This tutorial is focused on working with Gearbox's internals, it is not a course on UI design 🥲

In our Container element, we can include some basic formatting to better serve our data:

<div className="flex flex-col w-1/2"></div>

Now inside of this, we can iterate through our team data, using Array.map:

<h1 className="text-5xl font-bold ">Teams in the Database:</h1>
            <div className="divider mb-10"></div>
            {
                teams.map((team, index) => <div className="card bg-base-200 w-1/2" key={index}> 
                    <div className="card-body">
                        <h1 className="text-2xl font-semibold text-accent">{team.name} - {team.number}</h1>
                        <h2 className="text-xl">Participated for {team.seasons.length} seasons</h2>
                        <h2 className="text-md font-bold">{team.users.length} Members</h2>
                    </div>
                </div>)
            }

Now in it's complete glory, here is our final code:

//teamOverview.tsx
import { Team } from "@/lib/Types"; // Imports the Team type
import { useEffect, useState } from "react" // Imports basic functions from react

import { useCurrentSession } from "@/lib/client/useCurrentSession"; // imports a method for getting the user's current auth

import ClientAPI from "@/lib/client/ClientAPI"; // imports the client-side API
import Container from "@/components/Container"; // imports the container react component (which contains the nav-bar, auth verification, and header)

const api = new ClientAPI("gearboxiscool"); // create an instance of the client-side API, gearboxiscool is the private auth key

export default function TeamOverview() { // declare our react component

    const { session, status } = useCurrentSession(); // fetch your current session

    const[loading, setLoading] = useState(false);
    const[teams, setTeams] = useState<Team[]>([]);

    useEffect(() => {
        fetchData();
    }, []);

    const fetchData = async () => {
        setLoading(true); // set the fetching process
        const teamData: Team[] = await api.allTeams() // specific API path that gets every team in the database
        setTeams(teamData);
        setLoading(false); // all done!
    }

    return <Container requireAuthentication={true} hideMenu={false}>
        <div className="flex flex-col w-1/2 ml-10">
            <h1 className="text-5xl font-bold ">Teams in the Database:</h1>
            <div className="divider mb-10"></div>
            {
                teams.map((team, index) => <div className="card bg-base-200 w-1/2" key={index}> 
                    <div className="card-body">
                        <h1 className="text-2xl font-semibold text-accent">{team.name} - {team.number}</h1>
                        <h2 className="text-xl">Participated for {team.seasons.length} seasons</h2>
                        <h2 className="text-md font-bold">{team.users.length} Members</h2>
                    </div>
                </div>)
            }
        </div>
    </Container> // create the barebones web page
}

Now once we login, have some pre-exisiting teams in the database, we can view our masterpiece at https://localhost:3000/teamOverview.

Clone this wiki locally