Huu Thang's blog

Here Come a Kaomoji and GIF Search (ノ◕ヮ◕)ノ*:・゚✧


Jun 1, 2026 (updated: 1 week ago)

The comment section on this blog is finally getting the upgrade it deserved. No more static placeholders or limited text. You can now reply to threads directly and use markdown shortcuts including adding GIFs and Kaomojis.

I ended up building a custom Markdown Editor from scratch to handle all of this. Here is how it works and what went into it.

Note: GIFs and kaomojis can only be inserted through the platform's built-in tools - either via slash commands or the toolbar drawers. You still can paste external GIF links or raw kaomoji text directly; the editor handles the insertion and renders them properly.


The Markdown Helper and Shortcuts ( ˘ ³˘)♥

To make formatting less of a guessing game, I built a quick syntax reference panel directly into the editor view.

The editor now supports standard formatting essentials, along with some quality-of-life shortcuts:

  • Toolbar and Keyboard Shortcuts: You can use standard bindings like Ctrl/Cmd + B for bold or Ctrl/Cmd + I for italics to instantly wrap your text selection.
  • Smart Mentions: Typing @username triggers a dynamic user suggestion overlay that you can navigate using your arrow keys.

But the core feature of this platform upgrade is how it handles Kaomojis and GIFs.


Dual-Mode Searching: Slash Commands vs. Drawers

I wanted the editing experience to feel seamless whether you prefer keeping your hands on the keyboard or clicking through a visual menu. Because of that, every feature can be accessed in two different ways.

The Keyboard-First Way (Command Syntax) ☆*:.。.o(≧▽≦)o.。.:*☆

If you hate breaking your typing flow, you can query our databases directly using slash commands right in the textarea:

  • /kao <mood>: Typing something like /kao joy parses your text on the fly and brings up an auto-complete list of relevant text expressions. If you happen to type an unknown mood like /kao das, the UI safely falls back to alternative suggestion chips like faces or games so you are not stuck.
  • /gif <query>: Typing a command like /gif celebration opens an inline suggestion overlay pulling instant results from our GIF provider. This allows you to arrow down, hit Enter, and automatically replace the slash command with the full markdown image link - for example ![Jake Gyllenhaal Love GIF](https://media0.giphy.com/.../giphy.gif) - ready to render in your post.

The Visual Way (Selection Drawers)

Since inline commands only show a limited selection, you can open the toolbar drawers to access more items:

  • Clicking the Kaomoji icon opens a categorized grid with a live preview window so you can search even more expressions in it. ★~(◠‿◕✿)
  • Clicking the GIF icon brings up a scrollable grid with pagination ("Load More") for broader visual searches.

Handling Complex Syntax Under the Hood (¬_¬")

One minor technical challenge was keeping the markdown parser from breaking. Standard markdown sometimes treats specific characters inside a complex text face - such as underscores (_) or asterisks (*) - as formatting triggers. This accidentally causes words to italicize or turn bold.

To fix this, I introduced an extended markdown block specifically for expressions:

@@[ ( ◡‿◡ ♡) ]@@

Wrapping them in @@[...]@@ ensures that the internal text stays tightly grouped together as a literal string. This protects the layout from unexpected parsing bugs.


Thanks to Svelte's reactive component binding, the frontend remains incredibly snappy, and the backend handles the quick command parsing without breaking a sweat. ★~(◠‿◕✿) Give the new reply trees a spin below, use a shortcut, or test out a slash command to see it in action!


The Kaomoji API is Public ♪(┌・。・)┌ The kaomoji search server powering the /kao commands is something I ended up open-sourcing. You are welcome to use it for your own projects.

Repo: https://github.com/lhuthng/kaomojis Live: https://kaomoji-search.netlify.app/

Please don't DDoS it. Rate limiting exists but it is not fully hardened yet - I am still working on that. Be reasonable. (ง •_•)ง

TL;DR - the API call is just:

GET /:mood

Hit it with a mood keyword and you get back an array of matching kaomojis. For example:

GET /joy
json{
  "mood": "joy",
  "results": ["(≧▽≦)", "ヽ(・∀・)ノ", "..."],
  "total": 42,
  "page": 1,
  "limit": 20
}

You can also paginate with ?page=2&limit=10 if you want to page through the full set.

How the Fallback and Matching Work

When you type /kao das - a mood that does not exist - the server does not just throw a bare 404. It runs a Levenshtein distance calculation against every known mood key to find the closest matches and returns them as suggestions in the error body, so the UI can offer chips like faces or games instead of leaving you with nothing.

The scoring combines edit distance with a normalized similarity ratio, and prefix matches are always ranked above fuzzy ones. So /kao jo will surface joy before anything else, while a total mismatch like /kao das still tries to find something useful within a similarity threshold of 0.4.

Input length is also validated dynamically: the server measures the longest real mood key in the dataset, multiplies it by 1.5, and uses that ceiling to reject anything obviously outside range before it even hits the lookup logic.

There is also a simple sliding window rate limiter (60 requests per minute per IP) and a 5-minute in-memory cache keyed on mood:page:limit to keep repeated slash-command queries cheap on the server side.


Go Explore ♪(┌・。・)┌

The comment section is right below - go poke around. Try a /kao or /gif command, open the drawers, drop a reaction, start a thread. This whole thing was built to be played with, so don't hold back. (ง •_•)ง

Questions, bug reports, feature ideas - all welcome. Leave a comment and let me know what you think!


Written by:

Table of contents

Join the discussion!


comment-posting-avatar
Live Preview

Nothing to preview yet. Start typing...

Markdown Editor