Caching emotes for fast selection & embedding

#cache
#performance
#chat
#emotes

When building an emote picker or chat embed, fetching emotes on every render is expensive. The fix is to separate metadata from assets and cache both layers.

Cache emote metadata (IDs, names, URLs)

Store a lightweight index in memory (or Redis) for fast lookup by name.

// emoteCache.ts
type Emote = {
  id: string;
  name: string;
  url: string;
  provider: "twitch" | "bttv" | "7tv" | "local";
};

const emoteIndex = new Map<string, Emote>();

export function warmEmoteCache(emotes: Emote[]) {
  for (const emote of emotes) {
    emoteIndex.set(emote.name, emote);
  }
}

export function getEmoteByName(name: string) {
  return emoteIndex.get(name);
}

This lets your picker and message parser resolve :emote: tokens without touching the network.

Cache image assets at the edge or CDN

Serve emote images from a stable path and let the browser/CDN handle caching:

Cache-Control: public, max-age=31536000, immutable

Tailwind CSS !important modifier

#tailwindcss
#css

Make any utility important by adding a ! character to the beginning:

<p class="font-bold !font-medium">
  This will be medium even though bold comes later in the CSS.
</p>

Official Docs

nested backdrop-filter

#css

Backdrop filter will not work if the parent also has a backdrop-filter effect.

issueworkaround

pre overflow: scroll inside flex

#css
#pre
#flex

Ever used overflow-x: scroll on a pre element but it didn’t work, and instead the parent ended up scrolling?

The parent might be inside a display: flex. If so, try adding min-width: 0 to the parent.

Credit

import mdx file sebagai component

#react
#mdx

Import an MDX file in a component, similar to importing a regular component:

import Contents from '@/mdx/Contents.mdx';

// Usage
<Contents />

Turns out it’s in the documentation. Get used to reading it first, don’t be like me lol.

:not() pseudo-class

#css
#selector

Using :not() can be tricky, and incorrect usage can lead to unexpected results.

Example: styling inline code that is not a child of pre or .code-block. Usage:

Don't
:not(pre), :not(.code-block) {
  > code {
    background-color: 'red';
  }
}
Do
:not(pre, .code-block) {
  > code {
    background-color: 'red';
  }
}

Turborepo dependsOn

#turborepo
#monorepo
"build": {
  "dependsOn": ["^lint", "test"]
},

dependsOn with ^ indicates tasks from other packages, while without ^ indicates tasks from the same package.

Example: when app A builds, it must run the lint tasks in all its dependency packages, and also run the test task in app A itself.

e.target.valueAsNumber

#html
#js

Use e.target.valueAsNumber to automatically return the input value as a number. No need for parseInt(e.target.value) anymore.