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
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.
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:
- The main content area with information about the selected topic of the language
- The sidebar with links to more topics regarding the selected language.
There is also a dropdown in the navigation for easier switching of language paths.
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 Page Concept
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:
- Folder Structure for:
- Language Files
- Components for functionality
- Layout Components
- SEO with next-seo
- 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:
The lookup file:
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