@@ -34,6 +34,9 @@ const nextConfig: NextConfig = {
3434 async redirects ( ) {
3535 const redirectList = [ ] ;
3636
37+ // Normalizes text to a URL-friendly slug
38+ // e.g., "Example API" -> "example-api"
39+ // With preserveDots=true: "twilio.com" -> "twilio.com"
3740 const normalizeSlug = ( text : string , preserveDots = false ) => {
3841 return text
3942 . toLowerCase ( )
@@ -42,7 +45,9 @@ const nextConfig: NextConfig = {
4245 . replace ( / ^ - + | - + $ / g, "" ) ;
4346 } ;
4447
45- const normalizeServiceSlug = ( service : string ) => {
48+ // Converts service name to legacy format (underscores become dashes)
49+ // e.g., "twilio_media_v1" -> "twilio-media-v1"
50+ const toLegacyServiceSlug = ( service : string ) => {
4651 return service
4752 . toLowerCase ( )
4853 . replace ( / [ \( \) ] / g, "" )
@@ -51,23 +56,38 @@ const nextConfig: NextConfig = {
5156 . replace ( / ^ - + | - + $ / g, "" ) ;
5257 } ;
5358
59+ // Preserves the original service slug format (keeps underscores)
60+ // e.g., "twilio_media_v1" -> "twilio_media_v1"
61+ const toCurrentServiceSlug = ( service : string ) => {
62+ return service . toLowerCase ( ) ;
63+ } ;
64+
5465 for ( const key in list ) {
5566 if ( ! Object . prototype . hasOwnProperty . call ( list , key ) ) continue ;
5667
68+ // Parse the key format "provider:service" or just "provider"
5769 const [ provider , service ] = key . split ( ":" ) ;
5870 if ( ! provider ) {
5971 console . warn ( `Invalid key format: ${ key } ` ) ;
6072 continue ;
6173 }
6274
63- const legacyFullSlug = normalizeSlug ( key ) ;
64- const currentProviderSlug = normalizeSlug ( provider , true ) ;
65- const legacyProviderSlug = normalizeSlug ( provider . replace ( / \. / g, "-" ) ) ;
75+ // Generate different slug formats for redirects
76+ // e.g., key="twilio.com:twilio_media_v1"
77+ const legacyFullSlug = normalizeSlug ( key ) ; // "twilio-com-twilio-media-v1"
78+ const currentProviderSlug = normalizeSlug ( provider , true ) ; // "twilio.com"
79+ const legacyProviderSlug = normalizeSlug ( provider . replace ( / \. / g, "-" ) ) ; // "twilio-com"
80+
81+ const currentServiceSlug = service ? toCurrentServiceSlug ( service ) : null ; // "twilio_media_v1"
82+ const legacyServiceSlug = service ? toLegacyServiceSlug ( service ) : null ; // "twilio-media-v1"
6683
84+ // Build the canonical destination URL
6785 const destination = service
68- ? `/apis/${ encodeURIComponent ( currentProviderSlug ) } /${ encodeURIComponent ( normalizeServiceSlug ( service ) ) } `
86+ ? `/apis/${ encodeURIComponent ( currentProviderSlug ) } /${ encodeURIComponent ( currentServiceSlug ! ) } `
6987 : `/apis/${ encodeURIComponent ( currentProviderSlug ) } ` ;
7088
89+ // Redirect duplicate provider-only URLs
90+ // e.g., /apis/example.com/example.com -> /apis/example.com
7191 if ( ! service ) {
7292 redirectList . push ( {
7393 source : `/apis/${ encodeURIComponent ( currentProviderSlug ) } /${ encodeURIComponent ( currentProviderSlug ) } ` ,
@@ -76,6 +96,18 @@ const nextConfig: NextConfig = {
7696 } ) ;
7797 }
7898
99+ // Redirect from legacy service slug (dashes) to current service slug (underscores preserved)
100+ // e.g., /apis/twilio.com/twilio-media-v1 -> /apis/twilio.com/twilio_media_v1
101+ if ( service && legacyServiceSlug !== currentServiceSlug ) {
102+ redirectList . push ( {
103+ source : `/apis/${ encodeURIComponent ( currentProviderSlug ) } /${ encodeURIComponent ( legacyServiceSlug ! ) } ` ,
104+ destination,
105+ permanent : true ,
106+ } ) ;
107+ }
108+
109+ // Redirect from legacy full slug format
110+ // e.g., /apis/twilio-com-twilio-media-v1 -> /apis/twilio.com/twilio_media_v1
79111 if ( legacyFullSlug !== currentProviderSlug ) {
80112 redirectList . push ( {
81113 source : `/apis/${ encodeURIComponent ( legacyFullSlug ) } ` ,
@@ -84,6 +116,8 @@ const nextConfig: NextConfig = {
84116 } ) ;
85117 }
86118
119+ // Redirect from legacy provider slug (dots replaced with dashes)
120+ // e.g., /apis/twilio-com -> /apis/twilio.com
87121 if ( legacyProviderSlug !== currentProviderSlug ) {
88122 redirectList . push ( {
89123 source : `/apis/${ encodeURIComponent ( legacyProviderSlug ) } ` ,
0 commit comments