DEV Community

ggwork
ggwork

Posted on

From "What's the MIME for That?" to a 200+ Entry Reference Tool

You know that moment when you're building an upload feature and you need to validate file types, and you find yourself Googling "what's the MIME type for .webp" for the fifth time that week? That was me last month. I was working on a file upload handler and kept hitting the same wall: I'd remember common ones like image/jpeg, but then I'd need something obscure like .avif or .m4a and I'd be back to searching.

The worst part? The answers were scattered across MDN docs, Stack Overflow threads from 2012, and random GitHub gists with questionable accuracy. I wanted a single source of truth I could reference quickly.

The "Just Build It" Temptation

I considered just hardcoding the few types I needed. But I knew that was a band-aid. I'd be back in the same spot next week with a different project. So I did what any reasonable developer would do: I decided to build a comprehensive reference tool.

Because apparently I enjoy reinventing wheels.

The Data Problem

The first challenge was obvious: I needed a solid MIME type database. Not just the common ones — I wanted coverage across documents, images, video, audio, archives, code, fonts, and "other" stuff that doesn't fit neatly anywhere.

Here's what I learned: there's no official "MIME type registry" that's both comprehensive and easy to consume. The IANA registry is the authority, but it's a massive HTML table that's painful to scrape. I ended up cross-referencing:

  • The IANA registry (for official types)
  • MDN's MIME type documentation (for practical usage)
  • My own experience (for the "what people actually use" factor)

The data structure ended up being refreshingly simple:

{ ext: '.webp', mime: 'image/webp', cat: 'img', desc: 'WebP 图片' }
Enter fullscreen mode Exit fullscreen mode

That's it. Four fields. No relational database, no API calls — just a plain array in JavaScript.

The Search Logic: Simpler Than You'd Think

The search was the fun part. I wanted bidirectional lookup — type an extension and get the MIME, or type a MIME and get extensions. My first approach was embarrassingly over-engineered. I was thinking about fuzzy matching, Levenshtein distances, the whole nine yards.

Then I realized: developers searching for MIME types aren't typos. They know exactly what they're looking for. They just need quick verification. So I kept it simple:

  • Strip leading dots from the input
  • Case-insensitive substring matching
  • Check against extension, MIME type, and description

The debounce was the only "fancy" part — 200ms to prevent the render function from firing on every keystroke. The whole search logic fits in about 15 lines.

The AI Collaboration Experiment

Here's where things got interesting. I decided to build this with AI assistance — not as a gimmick, but because I genuinely wanted to see how well it could handle a well-specified, self-contained project. This felt like the perfect test case: clear requirements, no external dependencies, pure frontend.

I gave the AI a detailed spec: the exact data structure, the interaction patterns, the UI layout, even the SEO tags. The first attempt was... surprisingly good. It nailed the structure and the search logic on the first try.

But it completely missed the dark mode support. Classic "works on my machine" situation — the AI assumed everyone uses light mode.

The iteration process was where the real value came through. I'd say "add prefers-color-scheme media queries" and it would generate the CSS. Then I'd notice the category badges were unreadable in dark mode, and it would fix those specific color values. It was like pair programming with a very fast, slightly forgetful junior developer.

The part where I had to step in? The data. The AI's initial MIME database was thin — maybe 60 entries. I had to explicitly list the file types I wanted covered: "add these: cpp, java, py, go, rs, woff, woff2, ttf, otf..." That's the kind of domain knowledge that AI still can't fully replicate.

The i18n Surprise

I initially thought internationalization would be the hardest part. I was planning a full i18n library integration. But for a tool like this, a lightweight approach made more sense:

const i18n = {
  zh: { title: 'Content-Type 查询', searchPlaceholder: '输入扩展名或MIME...' },
  en: { title: 'Content-Type Lookup', searchPlaceholder: 'Enter extension or MIME...' }
};
Enter fullscreen mode Exit fullscreen mode

Just a simple dictionary with a language switcher. The descriptions in the database stay in their original language — which actually makes sense because MIME types themselves are language-agnostic. The tool is for developers, and developers know what image/jpeg means regardless of their native language.

The Copy Interaction

The click-to-copy feature was a requirement I initially underestimated. I thought navigator.clipboard.writeText() was a solved problem. Turns out, it has a subtle gotcha: it only works in secure contexts (HTTPS or localhost). For a tool that people might open as a local HTML file, I needed a fallback.

The fallback is the old-school approach:

const textarea = document.createElement('textarea');
textarea.value = mime;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
Enter fullscreen mode Exit fullscreen mode

It's deprecated, but it works everywhere. The lesson here: don't assume modern APIs are universally available, even for a "modern" tool.

Performance: The "It's Just an Array" Moment

I spent way too long thinking about performance optimization. Should I use a Map? A binary search tree? Index the data by extension?

Then I realized: the entire dataset is 215 entries. The search runs in milliseconds even with a naive filter. The only performance consideration that actually mattered was the debounce on the search input, and even that was more about avoiding excessive DOM updates than actual CPU usage.

The table rendering? I'm just regenerating the HTML string and setting innerHTML. It's not React, but it's also not 10,000 rows. Sometimes the simplest solution is the right one.

The Stats That Matter

One feature I'm glad I added: the result counter. It shows "X results out of Y total entries." It sounds trivial, but when you're searching for something and get zero results, seeing "0 results out of 215 entries" is much more reassuring than just "No results found." It confirms the tool is working — you just searched for something that doesn't exist in the database.

Speaking of no results: I made sure to include a friendly empty state. Because nothing kills developer trust faster than a blank screen with no explanation.

What I'd Do Differently

If I were to rebuild this, I'd probably add a "random MIME type" button. Not because it's useful, but because it's fun. Sometimes you want to test how your code handles unexpected input.

I'd also consider adding copy feedback per-row instead of a global status message. Right now, clicking any row copies the MIME and shows a status bar message. It works, but a per-row "copied!" tooltip would be more immediate feedback.

The Verdict on AI-Assisted Development

This project was a genuine test of AI-assisted development, and my honest take is: it's great for boilerplate and structure, but it still needs a human for judgment calls.

The AI handled the CSS layout, the search logic, the i18n structure, and even the SEO meta tags without complaint. It made mistakes — the dark mode oversight being the biggest one — but they were easy to catch and fix.

What the AI couldn't do was understand the subtle requirements that come from real-world usage. It didn't know that .docx is more common than .doc in 2024. It didn't know that application/x-www-form-urlencoded deserves a spot in the database even though it's not a file extension. Those insights come from experience, not from training data.

The Takeaway

I built this tool because I was tired of searching for MIME types. The process taught me that even "boring" developer tools have interesting engineering decisions lurking beneath the surface. The data structure matters more than the algorithm. The UX details (like the result counter and empty states) matter more than the feature list.

And if you're wondering: yes, I still Google MIME types sometimes. But now I have a better starting point.


During this process, I built a small browser-based tool to make this workflow easier. If you're dealing with the same problem, you can find it at Craftvo's Content-Type Lookup. It's just a plain HTML file with vanilla JS — no build tools, no frameworks, no server. Open it, search, copy, move on with your life.


Tags: mime-types, web-development, javascript, developer-tools, ai-assisted-development

Top comments (0)