Overview
The slugify utility function converts any string into a URL-friendly slug format. It’s used throughout the application to create clean, readable URLs for podcast episodes.
Function Signature
sluggify ( text : string ): string
Parameters
The text string to convert into a slug. Can include spaces, special characters, uppercase letters, and Unicode characters.
Return Value
A lowercase, hyphen-separated string with special characters removed, suitable for use in URLs.
The function applies the following transformations in order:
Convert to string - Ensures the input is a string
Lowercase - Converts all characters to lowercase
Trim - Removes leading and trailing whitespace
Replace spaces - Converts spaces to hyphens
Remove special characters - Keeps only word characters and hyphens
Collapse hyphens - Replaces multiple consecutive hyphens with a single hyphen
Remove leading hyphens - Removes hyphens from the start
Remove trailing hyphens - Removes hyphens from the end
Source Code
From /home/daytona/workspace/source/src/utils/slugify.js:
export function slugify ( text ) {
return text
. toString () // Convert to string
. toLowerCase () // Convert to lowercase
. trim () // Remove whitespace from both ends
. replace ( / \s + / g , "-" ) // Replace spaces with hyphens
. replace ( / [ ^ \w- ] + / g , "" ) // Remove all non-word chars except hyphens
. replace ( /- + / g , "-" ) // Replace multiple hyphens with single hyphen
. replace ( / ^ - + / , "" ) // Remove hyphens from start
. replace ( /- + $ / , "" ); // Remove hyphens from end
}
Usage Examples
Creating Podcast URLs
From /home/daytona/workspace/source/src/components/PodcastList/PodcastList.jsx:63:
import { slugify } from "../../utils/slugify" ;
const PodcastList = ({ onPlayPodcast }) => {
const navigate = useNavigate ();
const handlePodcastClick = ( song ) => {
navigate ( `/podcast/ ${ slugify ( song . title ) } ` );
};
return (
< div >
{ podcasts . map (( song ) => (
< div
key = { song . id }
onClick = { () => handlePodcastClick ( song ) }
>
{ song . title }
</ div >
)) }
</ div >
);
};
Finding Podcasts by Slug
From /home/daytona/workspace/source/src/components/PodcastDetail/PodcastDetail.jsx:187:
import { slugify } from "../../utils/slugify" ;
import { useParams } from "react-router-dom" ;
const PodcastDetail = ({ onPlayPodcast }) => {
const { id } = useParams (); // This is the slug from the URL
// Find the podcast by comparing slugified titles
const foundPodcast = songs . find (( song ) => slugify ( song . title ) === id );
if ( ! foundPodcast ) {
return < NotFound /> ;
}
return < div > { foundPodcast . title } </ div > ;
};
Basic Examples
Special Characters
Edge Cases
Real Podcast Titles
slugify ( "Hello World" );
// Output: "hello-world"
slugify ( "Nadie Sabe Nada" );
// Output: "nadie-sabe-nada"
slugify ( "Episode #123: The Best Episode!" );
// Output: "episode-123-the-best-episode"
Common Use Cases
URL Generation
Create SEO-friendly URLs from podcast titles:
const podcastUrl = `/podcast/ ${ slugify ( podcast . title ) } ` ;
// Result: "/podcast/nadie-sabe-nada-episodio-350"
Route Matching
Match URL slugs to podcast titles:
const podcast = allPodcasts . find ( p => slugify ( p . title ) === urlSlug );
Unique Identifiers
Generate consistent identifiers from titles:
const podcastId = slugify ( podcast . title );
localStorage . setItem ( `podcast- ${ podcastId } -progress` , currentTime );
Search Indexing
Create searchable keys:
const searchIndex = podcasts . map ( p => ({
id: p . id ,
slug: slugify ( p . title ),
title: p . title
}));
Best Practices
Always use slugify consistently when creating and matching URLs. If you slugify when creating a URL, you must slugify when looking it up.
The function removes special characters including accented characters (á, é, í, ó, ú, ñ). Two different podcast titles could theoretically produce the same slug. Consider adding a unique identifier if this is a concern.
The slugified version is not reversible - you cannot get the original title back from the slug. Always store both the original title and use the slug only for URLs.
Character Handling
Input Output Reason Spaces Hyphens URL-friendly Uppercase Lowercase Consistency Accents (á, é, etc.) Removed ASCII-only Special chars (!@#$%) Removed URL-safe Multiple hyphens Single hyphen Clean format Leading/trailing hyphens Removed Clean format
Technical Details
Regular Expressions Used
/ \s + / g // Matches one or more whitespace characters
/ [ ^ \w- ] + / g // Matches any character that's not a word char or hyphen
/- + / g // Matches one or more consecutive hyphens
/ ^ - + / // Matches hyphens at the start
/- + $ / // Matches hyphens at the end
Word Characters
The \w character class matches:
Lowercase letters (a-z)
Uppercase letters (A-Z)
Digits (0-9)
Underscore (_)
Alternatives and Extensions
For more advanced slug generation with better Unicode support, consider:
// With transliteration for better accent handling
import slugify from 'slugify' ;
const advancedSlugify = ( text ) => {
return slugify ( text , {
lower: true ,
strict: true ,
remove: / [ *+~.()' \" ;:@ ] / g
});
};
advancedSlugify ( "¡Vuelve Nadie Sabe Nada!" );
// Output: "vuelve-nadie-sabe-nada" (with proper accent handling)
However, the current implementation is lightweight with zero dependencies and works well for the application’s needs.