Kimon (鬼門)

Kimon (鬼門)

Next.jsReactTypeScriptTailwind CSSshadcn/uiSupabasePostgreSQLVercel

What it is

Kimon is a listening and reading game for people learning Japanese. You choose a song and a difficulty, and the YouTube video plays with the lyrics shown line by line. When a line with a missing word comes up, the video pauses and you pick the right word out of four. The wrong choices sound the same as the right one, so you have to know the kanji, not just hear the sound.

Kimon (鬼門) means “demon gate”: in Japanese folklore, the northeast direction that demons and spirits pass through. You play as a yurei, a Japanese ghost you pick when you sign up. The three difficulties are demon ranks: yokai, oni and kishin. Each higher rank blanks more of the song. The tone is playful, not scary, and the Japanese text always comes first: headings use a brush font, while lyrics and answers use BIZ UDPGothic, a font made to be easy to read.

Features

  • Song catalog: browse by genre (anime, J-pop, city pop, Vocaloid, enka), search, and hand-picked collections, in a card or table view.
  • Game screen: the video, a karaoke-style lyric line, and four answer cards you can pick with the mouse or the 1-4 keys.
  • Word meanings: after you answer, a side panel shows what each option means and links to its Jisho page, so a wrong guess becomes a lesson.
  • Profile: past plays, best scores, favorite songs and achievements.
  • WaniKani connection: players who study with WaniKani can link their account to see their level and known kanji on their profile.
  • Song requests: players can ask for a song and talk with me about it in a short message thread.

How it works

The game. The game screen runs a small state machine with four steps: waiting, playing, question and done. It tells the YouTube player when to play, pause and seek. The player only handles one command at a time, so each command waits for the last one to finish, and a fast second command cancels the first instead of racing it. The video pauses a quarter second early to make up for seek lag, so the answer word is never heard before the question shows.

The server. The app runs on Next.js with the App Router on Vercel. Pages are server components that read from Supabase, and every write, such as saving a play or adding a favorite, is a server action that checks its input on the server. If saving a play fails, it is kept in the browser and sent again on the next visit.

The database. Supabase holds the catalog, the players and their plays. Row level security lets anyone read the catalog and lets players read and write only their own rows. Database triggers award achievements when a play is saved, limit how many song requests a player can have open, and make a player’s yurei permanent once picked. WaniKani tokens are stored encrypted in Supabase Vault and only the server can read them back.

The songs. Synced lyrics and their timestamps come from LRCLIB through a script that writes them as SQL. The questions themselves are written by hand: one blanked word per line, four real words as options, and a rank for each question. A second script checks every option against a dictionary to catch mistakes.

Design

The look is “ink brutalism”: thick black borders, hard offset shadows and a small set of colors taken from traditional Japanese inks, such as vermilion for the main actions and indigo for what is selected. Ukiyo-e prints in the public domain decorate the pages, with paper grain and printing effects drawn in CSS. Page changes use an ink brush transition, and every animation respects the reduced motion setting.

Gallery

Kimon (鬼門): browse
Kimon (鬼門): rank
Kimon (鬼門): gameplay
Kimon (鬼門): results