The Language Hub - Netlify x Hashnode Hackathon Submission

The Language Hub is a central place for your language learning needs. Getting you to what you need quickly and easily

The Language Hub - Netlify x Hashnode Hackathon Submission

I've never participated in a hackathon. Not because I didn't want to, more because when I did find them, their focus was on things beyond my skillset at the time.

Introduction

As I was reading through some articles, I saw Hashnode was hosting yet another Hackathon. I read through the requirements and the only major thing is it be open source.

So, I'm doing something close to my heart - a language hub, of sorts. A language reference book

Visit The Language Hub

Have a look at the code


The Idea

I've been learning and teaching languages for some time now. I often come across scenarios where it takes a lot of time to find information about a concept I'm trying to understand or explain - the important parts. My students have also come to me asking for me to explain something. To give them correct answers I have to search through quite a bit of information to do so.

My Thought

A central place - source of truth - that has the important parts of the language that you need to know. Be it French, Spanish, Russian, Mandarin...

A place to you to the important parts of a language quickly and easily.

Essentially, I would like to have a top bar where you choose your learning path. That would take you to the page of your chosen path.
That page will have a main content area and sidebar listing all the items related to it. Clicking an item in the sidebar would load that content in the main area.

This is a great undertaking and will need the participation from people from all over the world to bring it to life


How The Language Hub Works?

Arriving on the site, there are buttons for languages.

home page.png

Selecting a card will lead you to the detail page of the selected language. There you can learn about the language you have selected

The detail page is divided into two main sections:

  1. The main content area with information about the selected topic of the language
  2. The sidebar with links to more topics regarding the selected language.

detailpage.png

There is also a dropdown in the navigation for easier switching of language paths.

dropdown.png

Thanks to Tailwind, the site is responsive


The Process

Here is how I went about bringing this project to life

Tech Stack

I've chosen Nextjs, Markdown styled with TailwindCSS.

  • Next.js: It works best if everything is statically generated
  • TailwindCSS: It's the simplest way of styling that's no fuss
  • Markdown: It's a format that is simple to write in and won't give me too much trouble when handling pull requests
  • next-mdx-remote: To render the markdown files.
  • Chakra Ui: I added ChakraUI because I really didn't want to spend time fighting with a drop-down
  • Netlify: To deploy the app

Planning

Github Repository:

I set up the Github repository and made sure it's public.

Site Design:

A Figma design so I have an idea of what everything will look like.

Home.png Home Page Concept

Detail.png Detail Page Concept

File and Folder Structure:

As I wanted to have more than one language, the markdown files would have to be separated into their own folders

├── allLanguages
│   ├── languageOne
│   │   ├── file1.md
│   │   ├── file2.md
│   ├── languageTwo
│   │   ├── file!.md

Contribution guide:

Some simple guidelines for anyone who wants to contribute.


The Building

With the outline of what I'm doing, I move on to creation.

Setup Project

I fired up a new Nextjs project and immediately got some things out of the way:

  1. Folder Structure for:
    • Language Files
    • Components for functionality
    • Layout Components
  2. SEO with next-seo
  3. Avoidance of relative paths by using a jscofig.json file

Things I Had To Figured Out

RENDERING FILES FROM NESTED DIRECTORIES

The first main thing to figure out was how to dynamically render files in a nested directory using the directory name and file name as a slug.

SOLUTION

At its core, The Language Hub is a markdown blog of sorts. However, to get the paths of each file within each of the individual language folders needed a different approach.

Jon Peppnick was very helpful in solving this issue.

In addition to accessing the learn folder, I had to run a forEach loop for every folder in learn and another one for every file in those folders.
Then I extracted the file names without the extensions and those became the slugs. In addition to that, I also took the folder name the file was located in to form the complete path.

The steps were:

  • Access the learn directory
  • Run a forEach loop for every folder(learnPath) in the learn directory
  • Run a forEach for each file in the learnPaths
  • Extract the slug from the file names
  • Return the slugs and learnPath as params
export async function getStaticPaths() {

  // get the directory for all language info
  const learnDir = path.join("learn");

  // read the learn directory
  const languagePathsDirs = await fs.readdirSync(learnDir);

  // create empty array where all the paths will be added to
  const allPaths = [];

 // run a loop to get each folder in the learn directory
  languagePathsDirs.forEach((langPath) => {
    const langPathDir = path.join(learnDir, langPath);

   // read the  folders
    const files = fs.readdirSync(langPathDir);

    // run another loop to get the files in each of
    files.forEach((filename) => {
      const path = {
        params: {
          // extract the langPath
          langPath: langPath,
           // extract the file name to be used as part of the slug
          slug: filename.replace(".md", ""),
        },
      };
      // push the path to the empty array
      allPaths.push(path);
    });
  });

  return {
    // return the paths as params
    paths: allPaths,
    fallback: false,
  };
}

When the above code worked, a lot of the heavy lifting had been dealt with

Then it was now just passing the params to getStaticProps and then to the page component

RENDER LIST OF FILES FROM A LANGPATH IN THE SIDEBAR

Next, I had to figure out how to render the file names of a given language in the sidebar and be able to link to them. Essentially, I needed the name of each file in the individual folders, and those would become the sidebar menu items.

SOLUTION

This is when things got really interesting. The solution I arrived at was in two parts.
First, a file with the language paths (folders) as arrays of strings(the files).
Then a lookup file would take those arrays and render the array based on which path matched.

The language menus file looks like this:

menus.png

The lookup file:

lookup.png

I then called the lookup in the detail page and passed its result to the Sidebar component.

DROPDOWN IN NAVIGATION

My next task was to have a drop-down in the navigation bar with a list of all the languages currently available.

SOLUTION

This was the simpler of the tasks. To accomplish this, I had a file with all the languages available and their country flags. I mapped through them and displayed them in a menu from Chakra UI.

Here is the source code, we have some issues that are open

Styling the Site

When I got all that working I was very happy with the result, so I moved on to the look of the site.

I also made sure to have a custom 404 page that would nudge visitors to either request a language or contribute to the site.

Deploying The Language Hub

As It is a Netlify Hackathon, one of the requirements was that the app you make be deployed on Netlify.

Netlfy makes deploying your project a breeze. Either upload your static files or link a github repository

I logged into my Netlify account and chose the the-language-hub repo, and waited for Netlify to do the rest

I encountered some errors with the deploy, both of them my doing.

ERROR 1:

Netlify or Eslint didn't like the apostrophe I had on my 404.js page. It took me a bit of time to figure out what exactly was the issue. When I did I retried the deploy.

Then the second error arose...

ERROR 2:

The site deployed didn't show any issues in the deploy log. But when you visited the pages, you got a server error.

WHAT WAS WRONG?

I've been using Next.js so much, I'm used to adding revalidate to my getStaticProps. The thing with that is this only works when fallback in your getStaticPaths is set to anything other than false.
That is what I had done - set a revalidate for a fallback of false which resulted in a server error

I corrected that, then the app started working as I intended


What Am I Doing Now?

At the moment I am adding more language data, so the site doesn't seem empty.

Wanna add one of your own? Wanna offer some advice? Hit me up in the comments or on Twitter


The Result

All in all, I am happy with what I was able to learn and accomplish.

Check out The Language Hub

At the end of the day, this is your project. I may have thought of it, but I had everyone else in mind. I would greatly appreciate any feedback and suggestions you have.

I am also looking for people who want to help in the improving of languages that are there and the adding of another language.

Conclusion

My first hackathon experience was interesting. I loved the thrill of having a set time frame to think of an idea, work on it and realise it into something tangible.

I would very much like to participate in another hackathon again.


Thank you for reading, let's connect!

Thank you for visiting this little corner of mine. Let's connect on Twitter, Polywork and LinkedIn