Building UI Inside an App You Do Not Control
YouTube Playlist Search adds a search box to YouTube. Writing it took an afternoon. Keeping it alive through YouTube's redesigns is the actual work.
If you have a lot of YouTube playlists, saving a video is miserable. The “Save to playlist” popup gives you a scrolling list with no search field, so you hunt for the right playlist by eye, every single time.
YouTube Playlist Search injects the missing search field. Into that popup, into the playlists library page, and into YouTube Music’s add-to-playlist dialog.
The feature is a filtered list. Thirty lines. Everything hard about this extension is the part where it has to keep working.
You cannot hold on to a class name
YouTube’s markup is generated. Class names are not stable, element nesting shifts, and a component you anchored to can be replaced during a redesign you never hear about. Any extension that pins itself to a single selector is not shipped software, it is a countdown.
So detection runs as layered fallbacks, from most durable to least:
- The semantic tag name, which is the last thing anybody renames
- A known element ID
- An ARIA role, which is load-bearing for accessibility and so rarely churns
- A structural heuristic, meaning find the scrollable list that contains items that look like playlist rows
Each layer is individually breakable. All four failing at once takes a rewrite rather than a redesign. The ordering is deliberate: the checks that depend on meaning come first, and the checks that depend on appearance come last, because meaning changes far more slowly than appearance does.
Looking native without hardcoding what native looks like
The obvious way to make an injected input match YouTube is to copy the current font, sizes, and colours into your stylesheet. That looks perfect on the day you write it and slowly rots afterwards. It also breaks the instant someone switches theme.
Instead the field reads computed styles off its sibling elements at injection time and inherits from them. Whatever font stack, spacing, and colour the surrounding rows resolved to, the search box resolves to the same thing.
That single decision handles dark mode, light mode, YouTube Music’s different palette, and most typography changes, without any of them being handled explicitly. You are not matching a design system. You are deferring to whatever the design system currently happens to be.
What I took from it
Anchor to meaning, not to appearance. Tag names and ARIA roles outlive class names by years.
Degrade in layers. Four weak checks in sequence are more durable than one strong check on its own.
Inherit instead of copying. Every value you hardcode is a value you have promised to maintain forever.
Assume the platform will change without telling you. Because it will, and you will find out from a user.