Ultra-lightweight, tree-shakable slug generator with optional transliteration. 2.8kB minified (1.4kB gzip) for the core functionality, with locale-specific character maps available as separate, optional imports.
- 🚀 Tiny: Core is 2.8kB minified (1.4kB gzip), full API 5.7kB (2.3kB gzip)
- 🌳 Tree-shakeable: Import only what you need
- 🔒 No global state: Safe for serverless and testing
- ⚡ Fast: 2-3x faster than alternatives on large datasets
- 🌍 Unicode-ready: Optional locale packs for any language
- 📦 Modern ESM: First-class ES modules with TypeScript
- ⚙️ Preset modes: 'pretty' and 'rfc3986' configurations built-in
- 🔧 CLI tool: Use via
npx tiny-slugifyfor quick commands - 🛡️ Robust: Comprehensive fuzz testing for reliability
npm install tiny-slugifyimport { slugify } from "tiny-slugify/core";
slugify("Hello World"); // → 'Hello-World'
slugify("Café & Restaurant"); // → 'Cafe-Restaurant'import { createSlugifier, extend, baseMap } from "tiny-slugify";
import { deMap } from "tiny-slugify/locale/de";
const germanSlugify = createSlugifier({
map: extend(baseMap, deMap),
options: { lower: true },
});
germanSlugify("Ärger & Größe"); // → 'aerger-und-groesse'
germanSlugify("100%"); // → '100prozent'import { slugify } from "tiny-slugify/core";
// Pretty mode (preserves case, good for titles)
slugify("Hello World & Test", { mode: "pretty" }); // → 'Hello-World-and-Test'
// RFC3986 mode (lowercase, URL-safe)
slugify("Hello World & Test", { mode: "rfc3986" }); // → 'hello-world-and-test'# Basic usage
npx tiny-slugify "Hello World"
# → Hello-World
# With preset modes
npx tiny-slugify --mode=rfc3986 "Hello World & Test"
# → hello-world-and-test
# With custom options
npx tiny-slugify --replacement="_" --lower "Hello World"
# → hello_world
# Pipe input
echo "Hello World" | npx tiny-slugify --mode=pretty
# → Hello-WorldBasic slug generation with built-in character map.
import { slugify } from "tiny-slugify/core";
slugify("Hello World", {
replacement: "_", // Default: '-'
lower: true, // Default: false
strict: true, // Default: false
trim: true, // Default: true
collapse: true, // Default: true
fallback: false, // Default: false
mode: "rfc3986", // Default: undefined
remove: /[*+~.()'"!:@]/g, // Custom removal pattern
});Create a slugifier instance with custom character maps and default options.
import { createSlugifier, extend, baseMap } from "tiny-slugify";
import { frMap } from "tiny-slugify/locale/fr";
const frenchSlugify = createSlugifier({
map: extend(baseMap, frMap),
options: { lower: true, replacement: "-", mode: "rfc3986" },
});| Option | Type | Default | Description |
|---|---|---|---|
replacement |
string |
'-' |
Character to replace spaces |
lower |
boolean |
false |
Convert to lowercase |
strict |
boolean |
false |
Strip non-alphanumeric chars |
trim |
boolean |
true |
Trim replacement chars from ends |
collapse |
boolean |
true |
Collapse consecutive replacements |
fallback |
boolean |
false |
Use base64 fallback for empty results |
mode |
'pretty' | 'rfc3986' |
undefined |
Apply preset configuration |
remove |
RegExp | string | string[] |
/[^\w\s-]/g |
Pattern for chars to remove |
multiCharMap |
MultiCharMap |
{} |
Multi-character mappings |
{
replacement: '-',
lower: false, // Preserves original case
strict: false,
trim: true,
collapse: true,
fallback: false
}{
replacement: '-',
lower: true, // Forces lowercase
strict: false,
trim: true,
collapse: true,
fallback: false
}When enabled, provides a deterministic slug for strings that would otherwise result in empty output:
slugify("🎉"); // → ''
slugify("🎉", { fallback: true }); // → 'OGpvaXE' (base64-derived)
slugify(" ", { fallback: true }); // → 'ZW1wdHk' (base64-derived)Support for complex scripts with multi-character sequences:
import { createSlugifier, extend, baseMap } from "tiny-slugify";
import { hiMap, hiMultiCharMap } from "tiny-slugify/locale/hi";
const hindiSlugify = createSlugifier({
map: extend(baseMap, hiMap),
multiCharMap: hiMultiCharMap,
});
hindiSlugify("नमस्ते"); // → 'namaste'
hindiSlugify("क्ष"); // → 'ksha' (conjunct consonant)Merge character maps without mutating originals.
import { extend, baseMap } from "tiny-slugify";
import { deMap } from "tiny-slugify/locale/de";
const customMap = extend(baseMap, deMap, { "©": "copyright" });Merge multi-character maps for complex scripts.
import { extendMultiChar } from "tiny-slugify";
import { hiMultiCharMap } from "tiny-slugify/locale/hi";
import { heMultiCharMap } from "tiny-slugify/locale/he";
const combinedMultiChar = extendMultiChar(hiMultiCharMap, heMultiCharMap);tiny-slugify/locale/de- German (ä → ae, ß → ss, & → und)tiny-slugify/locale/fr- French (é → e, œ → oe, & → et)tiny-slugify/locale/hi- Hindi (अ → a, क्ष → ksha, & → aur) + multi-char
More locales coming soon! Contributions welcome.
The CLI is included with the package:
npm install tiny-slugify
# or for global use
npm install -g tiny-slugify# Basic usage
npx tiny-slugify "Hello World"
# Help
npx tiny-slugify --help
# Version
npx tiny-slugify --version
# Preset modes
npx tiny-slugify --mode=pretty "Hello World & Test"
npx tiny-slugify --mode=rfc3986 "Hello World & Test"
# Custom options
npx tiny-slugify --replacement="_" "Hello World"
npx tiny-slugify --lower --strict "Café & Restaurant"
npx tiny-slugify --fallback "🎉"
# Remove characters
npx tiny-slugify --remove="@." "hello@world.com"
# Pipe input
echo "Hello World" | npx tiny-slugify --mode=rfc3986| Option | Description | Example |
|---|---|---|
--mode <mode> |
Preset mode: 'pretty' or 'rfc3986' | --mode=rfc3986 |
--replacement <char> |
Replacement character | --replacement="_" |
--lower |
Convert to lowercase | --lower |
--strict |
Remove non-alphanumeric chars | --strict |
--no-trim |
Don't trim replacement chars | --no-trim |
--no-collapse |
Don't collapse consecutive chars | --no-collapse |
--fallback |
Use base64 fallback | --fallback |
--remove <pattern> |
Remove matching characters | --remove="@." |
--help |
Show help message | --help |
--version |
Show version number | --version |
| Package | Core Size | With Locales | Tree-shakeable | CLI |
|---|---|---|---|---|
slugify |
12.5kB | 12.5kB | ❌ | ❌ |
slug |
8.2kB | 8.2kB | ❌ | ✅ |
tiny-slugify |
2.8kB | 5.7kB | ✅ | ✅ |
Benchmarks on Node.js 20 (M1 MacBook Pro):
- tiny-slugify: ~50,000 slugs/sec
- slugify: ~22,000 slugs/sec
- slug: ~35,000 slugs/sec
Performance gains are most noticeable with:
- Large datasets (CSV processing, file system operations)
- Server-side rendering with many routes
- Client-side apps with heavy string processing
Drop-in replacement for basic usage:
- import slugify from 'slugify';
+ import { slugify } from 'tiny-slugify/core';
slugify('Hello World'); // Same API!For extended character support:
- import slugify from 'slugify';
+ import { createSlugifier, extend, baseMap } from 'tiny-slugify';
+ import { deMap } from 'tiny-slugify/locale/de';
- slugify('Über Café', { locale: 'de' });
+ const germanSlugify = createSlugifier({ map: extend(baseMap, deMap) });
+ germanSlugify('Über Café');For preset-like behavior:
- slugify('Hello World', { lower: true, strict: false });
+ slugify('Hello World', { mode: 'rfc3986' });- import slug from 'slug';
+ import { slugify } from 'tiny-slugify/core';
- slug('Hello World');
+ slugify('Hello World', { lower: true }); // slug defaults to lowercaseWith fallback behavior:
- slug('🎉'); // returns base64-like string
+ slugify('🎉', { fallback: true }); // similar behavior- ✅ Base64 fallback for empty results
- ✅ Preset modes ('pretty', 'rfc3986')
- ✅ CLI tool for npx usage
- ✅ Comprehensive fuzz testing
-
✅ Multi-character mapping support
-
✅ Hindi locale pack with Devanagari
-
✅ Trie-based longest-match algorithm
- ✅ Unicode well-formed check
- ✅ Collapse option for consecutive chars
- ✅ Enhanced test coverage
- ✅ Core slugification functionality
- ✅ German and French locale packs
- ✅ Tree-shakeable ES modules
- ✅ TypeScript support
We welcome contributions! Please see our Contributing Guide for details.
MIT © 2024
Made with ❤️ by the tiny-slugify team