Skip to main content
MIME type detection and content-type helpers for Remix. This package maps extensions to MIME types and provides utilities for charset and compressibility checks.

Installation

npm i remix

Features

  • MIME Detection - Detect MIME types from extensions and filenames
  • Content-Type Helpers - Build Content-Type values with charset handling
  • Compression Signals - Check whether a media type is likely compressible
  • Generated Data - Built from mime-db
  • Runtime Agnostic - Works everywhere JavaScript runs

API Reference

detectMimeType

Detects the MIME type for a given file extension or filename.
function detectMimeType(
  extension: string
): string | undefined
extension
string
required
File extension (with or without dot) or filename with path.
returns
string | undefined
The MIME type for the extension, or undefined if unknown.
import { detectMimeType } from 'remix/mime'

detectMimeType('txt') // 'text/plain'
detectMimeType('.txt') // 'text/plain'
detectMimeType('file.txt') // 'text/plain'
detectMimeType('path/to/file.txt') // 'text/plain'
detectMimeType('unknown') // undefined

detectContentType

Detects the Content-Type header value for a given file extension or filename, including charset for text-based types.
function detectContentType(
  extension: string
): string | undefined
extension
string
required
File extension (with or without dot) or filename with path.
returns
string | undefined
The Content-Type header value with charset if applicable, or undefined if unknown.
import { detectContentType } from 'remix/mime'

detectContentType('css') // 'text/css; charset=utf-8'
detectContentType('.json') // 'application/json; charset=utf-8'
detectContentType('image.png') // 'image/png'
detectContentType('path/to/file.unknown') // undefined

isCompressibleMimeType

Checks if a MIME type is known to be compressible.
function isCompressibleMimeType(
  mimeType: string
): boolean
mimeType
string
required
MIME type or full Content-Type header value.
returns
boolean
true if the MIME type is compressible, false otherwise.
import { isCompressibleMimeType } from 'remix/mime'

isCompressibleMimeType('text/html') // true
isCompressibleMimeType('application/json') // true
isCompressibleMimeType('image/png') // false
isCompressibleMimeType('video/mp4') // false

// Also accepts full Content-Type header values
isCompressibleMimeType('text/html; charset=utf-8') // true
isCompressibleMimeType('application/json; charset=utf-8') // true

mimeTypeToContentType

Converts a MIME type to a Content-Type header value, adding ; charset=utf-8 to text-based MIME types.
function mimeTypeToContentType(
  mimeType: string
): string
mimeType
string
required
The MIME type to convert.
returns
string
The Content-Type header value with charset if applicable.
Charset is added to:
  • text/* (except text/xml which has built-in encoding declarations)
  • application/json
  • application/javascript
  • All +json suffixed types
import { mimeTypeToContentType } from 'remix/mime'

mimeTypeToContentType('text/css') // 'text/css; charset=utf-8'
mimeTypeToContentType('application/json') // 'application/json; charset=utf-8'
mimeTypeToContentType('application/ld+json') // 'application/ld+json; charset=utf-8'
mimeTypeToContentType('image/png') // 'image/png'
mimeTypeToContentType('text/xml') // 'text/xml' (no charset added)

defineMimeType

Registers or overrides a MIME type for one or more file extensions.
function defineMimeType(
  definition: MimeTypeDefinition
): void
definition
MimeTypeDefinition
required
The MIME type definition to register.

MimeTypeDefinition

extensions
string[]
required
Array of file extensions (without dots) to associate with this MIME type.
mimeType
string
required
The MIME type string.
compressible
boolean
Whether the MIME type is compressible.Default: false
charset
string
The charset to use in Content-Type headers.Default: undefined
import { defineMimeType } from 'remix/mime'

// Basic definition
defineMimeType({
  extensions: ['myformat'],
  mimeType: 'application/x-myformat',
})

// With charset and compressibility
defineMimeType({
  extensions: ['myformat', 'myfmt'],
  mimeType: 'application/x-myformat',
  compressible: true,
  charset: 'utf-8',
})

Examples

Detect MIME Type from Filename

import { detectMimeType } from 'remix/mime'

function getMimeType(filename: string): string {
  return detectMimeType(filename) ?? 'application/octet-stream'
}

getMimeType('document.pdf') // 'application/pdf'
getMimeType('image.jpg') // 'image/jpeg'
getMimeType('styles.css') // 'text/css'
getMimeType('unknown.xyz') // 'application/octet-stream'

Set Content-Type Header

import { detectContentType } from 'remix/mime'

let filename = 'document.json'
let contentType = detectContentType(filename)

let response = new Response(data, {
  headers: {
    'Content-Type': contentType ?? 'application/octet-stream',
  },
})

Conditional Compression

import { isCompressibleMimeType } from 'remix/mime'
import { compressResponse } from 'remix/response/compress'

let response = new Response(data, {
  headers: { 'Content-Type': contentType },
})

if (isCompressibleMimeType(contentType)) {
  response = await compressResponse(response, request)
}

Custom MIME Type

import { defineMimeType, detectMimeType } from 'remix/mime'

// Register custom format
defineMimeType({
  extensions: ['mdx'],
  mimeType: 'text/mdx',
  compressible: true,
  charset: 'utf-8',
})

detectMimeType('document.mdx') // 'text/mdx'

File Upload Handler

import { detectMimeType, isCompressibleMimeType } from 'remix/mime'

function shouldCompress(filename: string): boolean {
  let mimeType = detectMimeType(filename)
  return mimeType ? isCompressibleMimeType(mimeType) : false
}

shouldCompress('document.txt') // true
shouldCompress('image.png') // false
shouldCompress('data.json') // true

Serve Static Files

import { detectContentType } from 'remix/mime'
import { createFileResponse } from 'remix/response/file'
import { openLazyFile } from 'remix/fs'

async function serveFile(path: string, request: Request): Promise<Response> {
  let file = openLazyFile(path)
  
  // The file's type is automatically detected from the extension
  // but you can also use detectContentType if needed
  let contentType = detectContentType(path) ?? 'application/octet-stream'
  
  return createFileResponse(file, request, {
    cacheControl: 'public, max-age=3600',
  })
}

Common MIME Types

Text

detectMimeType('txt')  // 'text/plain'
detectMimeType('html') // 'text/html'
detectMimeType('css')  // 'text/css'
detectMimeType('csv')  // 'text/csv'
detectMimeType('xml')  // 'text/xml'

Application

detectMimeType('json') // 'application/json'
detectMimeType('js')   // 'application/javascript'
detectMimeType('pdf')  // 'application/pdf'
detectMimeType('zip')  // 'application/zip'
detectMimeType('wasm') // 'application/wasm'

Image

detectMimeType('png')  // 'image/png'
detectMimeType('jpg')  // 'image/jpeg'
detectMimeType('jpeg') // 'image/jpeg'
detectMimeType('gif')  // 'image/gif'
detectMimeType('svg')  // 'image/svg+xml'
detectMimeType('webp') // 'image/webp'
detectMimeType('ico')  // 'image/x-icon'

Video

detectMimeType('mp4')  // 'video/mp4'
detectMimeType('webm') // 'video/webm'
detectMimeType('mov')  // 'video/quicktime'

Audio

detectMimeType('mp3')  // 'audio/mpeg'
detectMimeType('wav')  // 'audio/wav'
detectMimeType('ogg')  // 'audio/ogg'

Font

detectMimeType('woff')  // 'font/woff'
detectMimeType('woff2') // 'font/woff2'
detectMimeType('ttf')   // 'font/ttf'
detectMimeType('otf')   // 'font/otf'

Type Definitions

function detectMimeType(extension: string): string | undefined

function detectContentType(extension: string): string | undefined

function isCompressibleMimeType(mimeType: string): boolean

function mimeTypeToContentType(mimeType: string): string

interface MimeTypeDefinition {
  extensions: string[]
  mimeType: string
  compressible?: boolean
  charset?: string
}

function defineMimeType(definition: MimeTypeDefinition): void

Best Practices

Always Provide Fallback

// ✅ Good: Provide fallback for unknown types
let mimeType = detectMimeType(filename) ?? 'application/octet-stream'

// ❌ Bad: May result in undefined
let mimeType = detectMimeType(filename)

Use Content-Type for Headers

// ✅ Good: Use detectContentType for headers (includes charset)
let contentType = detectContentType('file.json')
// 'application/json; charset=utf-8'

// ❌ Less ideal: detectMimeType doesn't include charset
let mimeType = detectMimeType('file.json')
// 'application/json'

Check Compressibility

// ✅ Good: Check before enabling compression features
let acceptRanges = !isCompressibleMimeType(file.type)

let response = await createFileResponse(file, request, {
  acceptRanges, // Enable ranges only for non-compressible types
})
  • response - Uses MIME utilities for file responses
  • lazy-file - File implementation with MIME type support

Build docs developers (and LLMs) love