npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@bernierllc/slug-generator

v1.0.1

Published

SEO-friendly URL slug generation with Unicode support and collision handling

Downloads

115

Readme

@bernierllc/slug-generator

SEO-friendly URL slug generation with Unicode support and collision handling.

Installation

npm install @bernierllc/slug-generator

Features

  • 🌍 Unicode Support - Handles international characters (German ß, Spanish ñ, French é, etc.)
  • 🔄 Collision Detection - Generates unique slugs with numeric, random, or timestamp suffixes
  • ⚙️ Customizable - Configure separator, max length, case handling, and character replacements
  • 🎯 SEO-Optimized - Removes special characters, normalizes whitespace, truncates intelligently
  • 📦 Zero Dependencies - Pure TypeScript implementation
  • 🌐 Universal - Works in Node.js and browser environments

Usage

Basic Usage

import { generateSlug } from '@bernierllc/slug-generator';

const slug = generateSlug('Hello World!');
// Output: "hello-world"

const blogPost = generateSlug('How to Build a React App in 2025');
// Output: "how-to-build-a-react-app-in-2025"

Advanced Usage with Options

import { SlugGenerator } from '@bernierllc/slug-generator';

const generator = new SlugGenerator({
  separator: '_',
  maxLength: 50,
  lowercase: true,
  removeDiacritics: true,
  strict: true,
  replacements: {
    '&': 'and',
    '@': 'at',
    '%': 'percent'
  }
});

const result = generator.generate('A & B @ 50% Off!');
// Output: { slug: "a_and_b_at_50_percent_off", modified: true, changes: [...], truncated: false }

Unicode and International Characters

import { generateSlug } from '@bernierllc/slug-generator';

// German
generateSlug('Größe und Qualität');
// Output: "grosse-und-qualitat"

// Spanish
generateSlug('Niño en España');
// Output: "nino-en-espana"

// French
generateSlug('Crème brûlée au café');
// Output: "creme-brulee-au-cafe"

// Mixed
generateSlug('Café København Łódź');
// Output: "cafe-kobenhavn-lodz"

Collision Handling

import { generateUniqueSlug } from '@bernierllc/slug-generator';

const existing = ['hello-world', 'hello-world-1'];

// Numeric suffix (default)
const slug1 = generateUniqueSlug('Hello World', existing);
// Output: "hello-world-2"

// Random suffix
const generator = new SlugGenerator();
const result = generator.generateUnique('Hello World', {
  existing: ['hello-world'],
  suffixFormat: 'random'
});
// Output: { slug: "hello-world-a3f9k", ... }

// Timestamp suffix
const result2 = generator.generateUnique('Hello World', {
  existing: ['hello-world'],
  suffixFormat: 'timestamp'
});
// Output: { slug: "hello-world-l5m2n8p", ... }

Validation

import { isValidSlug } from '@bernierllc/slug-generator';

isValidSlug('hello-world'); // true
isValidSlug('hello world'); // false (contains space)
isValidSlug('hello-world!'); // false (contains special char)
isValidSlug(''); // false (empty)

API Reference

generateSlug(text: string, options?: SlugOptions): string

Generate a slug from text using default or custom options.

Parameters:

  • text - Input text to convert
  • options - Optional configuration (see SlugOptions)

Returns: Generated slug string

generateUniqueSlug(text: string, existing: string[], options?: SlugOptions): string

Generate a unique slug by adding suffixes to avoid collisions.

Parameters:

  • text - Input text to convert
  • existing - Array of existing slugs to check against
  • options - Optional configuration (see SlugOptions)

Returns: Unique slug string

isValidSlug(slug: string, options?: SlugOptions): boolean

Validate if a string is a valid slug.

Parameters:

  • slug - String to validate
  • options - Optional configuration (see SlugOptions)

Returns: true if valid, false otherwise

SlugGenerator

Main class for slug generation with instance-level configuration.

Constructor:

new SlugGenerator(options?: SlugOptions)

Methods:

  • generate(text: string): SlugResult - Generate slug with detailed result
  • generateUnique(text: string, options: CollisionOptions): SlugResult - Generate unique slug
  • isValidSlug(slug: string): boolean - Validate slug format

SlugOptions

Configuration options for slug generation:

interface SlugOptions {
  separator?: string;         // Default: '-'
  lowercase?: boolean;        // Default: true
  maxLength?: number;         // Default: 100
  removeDiacritics?: boolean; // Default: true
  strict?: boolean;           // Default: true (remove all non-alphanumeric)
  replacements?: Record<string, string>; // Custom character replacements
}

SlugResult

Detailed result from slug generation:

interface SlugResult {
  slug: string;           // Generated slug
  modified: boolean;      // Whether original text was changed
  changes: string[];      // List of transformations applied
  truncated: boolean;     // Whether slug was truncated
}

CollisionOptions

Options for handling slug collisions:

interface CollisionOptions {
  existing: string[];                           // Existing slugs to check
  suffixFormat?: 'numeric' | 'random' | 'timestamp'; // Default: 'numeric'
  maxAttempts?: number;                        // Default: 100
}

Configuration

Environment Variables

This package has no environment variables (pure utility - all configuration via options).

Runtime Configuration

All configuration is passed via constructor or function parameters:

// Instance configuration
const generator = new SlugGenerator({
  separator: '_',
  maxLength: 80,
  replacements: { '&': 'and' }
});

// Per-call configuration
const slug = generateSlug('Hello World', { separator: '_' });

Examples

Blog Post Slugs

import { generateSlug } from '@bernierllc/slug-generator';

const posts = [
  'How to Build a React App in 2025',
  'Top 10 JavaScript Tips & Tricks',
  'Understanding TypeScript Generics'
];

const slugs = posts.map(title => generateSlug(title));
// [
//   "how-to-build-a-react-app-in-2025",
//   "top-10-javascript-tips-tricks",
//   "understanding-typescript-generics"
// ]

Product URLs

import { SlugGenerator } from '@bernierllc/slug-generator';

const generator = new SlugGenerator({
  maxLength: 60,
  replacements: {
    '&': 'and',
    '%': 'percent',
    '$': 'dollar'
  }
});

const product = 'Nike Air Max 90 - Men\'s Running Shoes - $120';
const result = generator.generate(product);
// { slug: "nike-air-max-90-mens-running-shoes-dollar120", ... }

Content Management System

import { SlugGenerator } from '@bernierllc/slug-generator';

class ContentService {
  private generator = new SlugGenerator();

  async createPost(title: string) {
    // Get existing slugs from database
    const existingSlugs = await this.getExistingSlugs();

    // Generate unique slug
    const result = this.generator.generateUnique(title, {
      existing: existingSlugs,
      suffixFormat: 'numeric'
    });

    return {
      title,
      slug: result.slug,
      url: `/blog/${result.slug}`
    };
  }

  private async getExistingSlugs(): Promise<string[]> {
    // Database query
    return ['existing-post', 'another-post'];
  }
}

E-commerce Categories

import { generateSlug } from '@bernierllc/slug-generator';

const categories = {
  'Men\'s Clothing & Accessories': generateSlug('Men\'s Clothing & Accessories'),
  'Women\'s Shoes & Boots': generateSlug('Women\'s Shoes & Boots'),
  'Electronics & Gadgets': generateSlug('Electronics & Gadgets')
};

// {
//   "Men's Clothing & Accessories": "mens-clothing-accessories",
//   "Women's Shoes & Boots": "womens-shoes-boots",
//   "Electronics & Gadgets": "electronics-gadgets"
// }

Integration Status

Logger Integration

Status: Not applicable

Justification: This is a pure utility package with no runtime state, side effects, or error conditions that require logging. The SlugGenerator class is stateless and deterministic - it simply converts strings to URL-friendly slugs. All errors are thrown as exceptions that calling code can handle, and there are no background operations, network calls, or state changes that would benefit from structured logging.

Pattern: Pure functional utility - no logger integration needed.

NeverHub Integration

Status: Not applicable

Justification: This is a core utility package that provides slug generation functionality. It does not participate in service discovery, event publishing, or service mesh operations. It's a stateless utility that can be used by any service or application without requiring service registration or discovery.

Pattern: Core utility - no service mesh integration needed.

Docs-Suite Integration

Status: Ready

Format: TypeDoc-compatible JSDoc comments are included throughout the source code. All public APIs are documented with examples and type information.

Performance

  • Typical title (50 chars): <1ms
  • Long title (200 chars): <2ms
  • Unicode heavy (100 chars): <3ms
  • Collision detection (100 existing): <5ms

Browser Support

Works in all modern browsers and Node.js environments:

  • Node.js 16+
  • Chrome, Firefox, Safari, Edge (latest 2 versions)

License

Copyright (c) 2025 Bernier LLC. All rights reserved.

This file is licensed to the client under a limited-use license. The client may use and modify this code only within the scope of the project it was delivered for. Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.

Related Packages

Used By

  • @bernierllc/content-editor-service - Generates slugs for new content
  • @bernierllc/content-workflow-service - Slug validation and uniqueness
  • @bernierllc/social-publisher - URL generation for published content

Part Of

  • Content Management Suite - Blog content workflow and URL generation

Support

For issues, questions, or feature requests, please contact Bernier LLC.