Skip to main content

Slug Generation and Utilities

The template includes a slug utility module (lib/utils/slug.ts) that provides bidirectional conversion between human-readable text and URL-safe slugs. These functions are used throughout the application for generating route paths, filter URLs, and content identifiers.

Functions

slugify

Converts arbitrary text into a URL-safe slug string.

import { slugify } from '@/lib/utils/slug';

slugify('Hello World'); // "hello-world"
slugify('Rock & Roll'); // "rock-and-roll"
slugify(' Extra Spaces '); // "extra-spaces"
slugify('Special @#$% Chars!'); // "special-chars"
slugify('Multiple---Dashes'); // "multiple-dashes"
slugify(''); // ""

Implementation

export function slugify(text: string): string {
if (!text || typeof text !== 'string') {
return '';
}
return text
.toString()
.toLowerCase()
.trim()
.replace(/\s+/g, '-') // Replace spaces with hyphens
.replace(/&/g, '-and-') // Replace & with "-and-"
.replace(/[^\w\-]+/g, '') // Remove non-word characters
.replace(/\-\-+/g, '-') // Collapse multiple hyphens
.replace(/^-+|-+$/g, ''); // Trim leading/trailing hyphens
}

Transformation Steps

The function applies five sequential regex replacements:

StepPatternReplacementPurpose
1/\s+/g-Spaces become hyphens
2/&/g-and-Ampersands become "-and-"
3/[^\w\-]+/g""Strip special characters
4/\-\-+/g-Collapse consecutive hyphens
5/^-+|-+$/g""Remove leading/trailing hyphens

Input Safety

The function returns an empty string for falsy or non-string inputs:

slugify(null);      // ""
slugify(undefined); // ""
slugify(''); // ""
slugify(123); // "" (not a string)

deslugify

Converts a slug back into human-readable text. This is the inverse of slugify.

import { deslugify } from '@/lib/utils/slug';

deslugify('hello-world'); // "hello world"
deslugify('rock-and-roll'); // "rock&roll"
deslugify('project-management'); // "project management"
deslugify(''); // ""

Implementation

export function deslugify(slug: string): string {
if (!slug || typeof slug !== 'string') {
return '';
}
return slug
.replace(/-and-/g, '&') // Restore ampersands
.replace(/-/g, ' ') // Replace hyphens with spaces
.trim();
}

Transformation Steps

StepPatternReplacementPurpose
1/-and-/g&Restore ampersands first
2/-/g" "Remaining hyphens become spaces

The order matters: -and- is replaced before - to avoid partial replacement.

Usage Patterns

Route Generation

Generate URL paths from content titles:

import { slugify } from '@/lib/utils/slug';

const title = 'Project Management Tools';
const url = `/categories/${slugify(title)}`;
// "/categories/project-management-tools"

Display from URL Params

Convert route parameters back to display text:

import { deslugify } from '@/lib/utils/slug';

// In a page component receiving params
interface PageProps {
params: { slug: string };
}

export default function CategoryPage({ params }: PageProps) {
const displayName = deslugify(params.slug);
// "project management tools"

return <h1>{displayName}</h1>;
}

Tag and Category Filtering

The slug utilities integrate with the filter sync system for URL-friendly filter values:

import { slugify, deslugify } from '@/lib/utils/slug';

// Encode a tag for URL
const tagSlug = slugify('Time & Attendance');
// "time-and-attendance"

// Decode back for display
const tagDisplay = deslugify(tagSlug);
// "time&attendance"

Content Identifiers

Generate stable identifiers for content items:

import { slugify } from '@/lib/utils/slug';

function generateContentId(name: string): string {
const slug = slugify(name);
if (!slug) {
throw new Error('Cannot generate ID from empty name');
}
return slug;
}

Edge Cases

Inputslugify OutputNotes
"Hello World""hello-world"Standard case
"R&D Tools""r-and-d-tools"Ampersand expansion
" spaces ""spaces"Trimmed
"---dashes---""dashes"Leading/trailing dashes removed
"a--b--c""a-b-c"Consecutive dashes collapsed
"@#$%"""All special characters removed
""""Empty string passthrough
null""Null safety

Roundtrip Considerations

The slugify and deslugify functions are not perfect inverses. Information is lost during slugification:

slugify('Hello World!');  // "hello-world"
deslugify('hello-world'); // "hello world" (lowercase, no exclamation)

Specifically, slugify discards:

  • Original casing (everything is lowercased)
  • Special characters (except hyphens and ampersands)
  • Multiple consecutive spaces

For scenarios requiring perfect roundtrip fidelity, store the original text alongside the slug.

Source Files

FilePurpose
lib/utils/slug.tsSlug generation and reversal utilities