Type Korean

Korean Typing App

Introduction


While studying Korean, I noticed a gap between being able to write on paper and being able to type efficiently on a Korean keyboard. I was always used to romanized keyboards; the Korean keyboard layout and system are different. Since I couldn’t find a practice tool that fit my needs, I built one myself. Type Korean is a web app that guides users through lessons and exercises to help them improve at the Korean keyboard layout. This project taught me a lot about building user-centered tools and publishing web apps from development to a production server outside my own hosted environment.

Open the live app

1. Approach


The goal of this app was clear: create a web app that offers people lessons on how to type on the Korean keyboard, as simple as that. While it does sound simple, I had to define clear goals for the app:

  • Lightweight, no unnecessary frameworks; only Node.js, HTML, CSS, and JavaScript.
  • 2 Lesson options: practice with beginner words and lessons for advanced people.
  • A maximum of 5 pages.

2. Design


I started things off by whipping out Figma and designing some fire. Here is the dark theme Figma design that I went with:

Figma page design

As you can see, the design doesn’t look exactly like how the website is now. I started off with a dark blue theme which I then changed to a white and dark theme because I liked it a bit better. The design included 3 things:

  • Main page
  • Choosing lesson type
  • The actual lesson

After finalizing the design, I decided to build the project using Node.js with plain HTML, CSS, and JavaScript. I initially considered using React, but ultimately chose to keep this project simple and save React for a future, more complex build. Once the design and basic structure were in place, I moved on to the lessons page, where I began implementing the core logic that defines how the lessons function and interact with users.

3. Lessons


The goal of the lessons was straightforward: to create responsive, easy-to-follow lessons featuring a virtual keyboard that guides the user through each step. From a technical perspective, I wanted to follow my software engineering lecture and this part of the project required defining must-have, should-have, and won’t-have criteria, since it represented the core logic of my web app.

  • The app must display a virtual keyboard for the user.
  • The app must map the current layout of the user’s keyboard to the Korean layout.
  • The app must highlight the next key that needs to be typed and all other keys needed for the lesson.
  • The app must offer visual feedback if the typed characters are correct or wrong.
  • The app must display a lesson for the user and display words or characters that are needed to be typed for the lesson.
  • The app should offer many different types of lessons in order to learn every Korean key input.
  • The app should save the user’s progress.
  • The app will not offer a way to skip or bypass lessons.

With this I started designing the logic of the app. First I implemented the lessons inside a json file for both words and phrases, which follow this approach:

{
  "id": "vowel-a-basic",
  "title": "Vowel Focus: ㅏ",
  "description": "Build familiarity with the ㅏ vowel sound through repetitive, easy syllables.",
  "targets": ["ㅏ"],
  "repeatGoal": 3,
  "items": [
    { "id": "vowel-a-basic-001", "hangul": "아", "romanization": "a", "translation": "Syllable ah" }
  ]
}

Code Snippet: Example lesson structure

We define an id (the lesson name), the target key we want to practice, a title and description, and the items inside are the words that are displayed to type. We then map the keyboard to the Korean input and check inside an invisible input element if the typed syllable block is correct; if so, we move to the next exercise until the lesson is finished.

4. Visual feedback & Hangul


The Korean letter system is a bit similar to the Roman letter system. It is called Hangul and it is a phonetic script made up of 10 basic vowels and 14 basic consonants referred to as “jamo”.

Consonants and vowels of the korean alphabet

Consonants and vowels of the korean alphabet

It is fairly easy to understand. For example, we can write “banana” as: ㅂ ㅏ ㄴ ㅏ ㄴ ㅏ. But here’s the main difference: these letters are not written separately, they form syllable blocks, so‑called Hangul syllables. So the word “banana” would actually be written as 바나나. As you can see, they are stacked and there is no gap between them. They can be stacked on top of each other as well, like: 한글 (Hangul).

Image of how the korean jamos are stacked as syllable blocks

How korean letters (jamos) get stacked as syllable blocks

Designing visual feedback for the user sounded straightforward at first — just highlight the wrong letters in red and the correct ones in green, right? Simple. Or so I thought. In reality, this turned out to be surprisingly challenging to implement. For romanized languages, it’s easy: every key corresponds to a unique code (like a Unicode code point), so as the user types, you can directly highlight each letter. But Korean works differently; individual letters can combine and stack into a single syllable block, which itself is represented by just one code point. This makes it much harder to track and highlight individual keystrokes accurately.

Korean system and roman system

Image of romanized character represented as code point and Korean block

It’s like trying to take the letter “g”, split off just the hook at the bottom, and color only that part and then doing the same for every other possible letter. As you can imagine, that’s incredibly difficult to pull off using just HTML, CSS, and JavaScript. I spent over three days, working nearly 12 hours a day, experimenting with different approaches to solve this problem. It is possible, but it’s also painfully complex, time-consuming, and requires hundreds of lines of rule-based code. Eventually, I narrowed it down to two potential solutions:

  1. Write the letters separately and stack them to each other using a grid system.
    Hangul CSS Grid setup

    Hangul characters arranged inside a grid element

    This approach would require an excessive number of rules and still wouldn’t run efficiently. Korean syllable blocks are always rendered at a fixed size, which means the individual letters (jamos) inside them must adjust their own size and shape depending on how many are stacked together. On top of that, some letters even change their appearance slightly based on their position within the block. For example, the letter “g” (ㄱ) looks different depending on which syllable block it appears in.
Difference between 구 and 가

Image of 구 and 가

While it was technically possible, implementing it with pure HTML and CSS rules looked to be extremely difficult. This wasn’t consistent across all words, making it a less-than-ideal solution. After spending two full days experimenting and debugging, I decided to abandon this approach and move on.

  1. Write composite glyphs
    This solution consists of drawing each syllable and possible block independently and reusing them as svg. While this is possible and the results are amazing since you can then highlight each individual part of the Jamos, I deemed it as not an optimal solution again because of 2 reasons:
    • You have to draw each syllable block for your lessons. If you expand your lessons which maybe include syllable blocks that you didn’t draw, you have to draw them again and make sure they exist.
    • If you want to change the font, you have to redraw them all as well.

There are 11.172 possible combinations if we want to make sure to cover all syllables, which would take way too much storage sapce. We could, as an alternative draw around 80% of the most common ones, but once again, if we expand the app redrawing will be necessary, and as I explained I was looking for an optimal solution for this problem.

After three full days I decided to wrap this highly sophisticated system and go with a simpler approach: highlight the whole syllable block and offer a visualizer on how the keys are formed above the displayed text.

Lesson and block highlight

5. Outcomes & Next Steps


Closing this project felt meaningful: I solved a problem I personally had, focused on building an application that fit my needs, and released it to a production server outside my own hosting environment. The process taught me how to cut scope thoughtfully, design around real constraints, and ship something reliable.

I plan to keep sending updates from time to time; expanding lessons, improving progress tracking, and exploring different types of lessons; maybe ones including practice for the Sejong Hakdang colloqium that I'm attending. I truly hope this app has helped people improve their typing and that they’ve seen significant progress.