1
+ import { Suspense } from 'react'
2
+ import { notFound } from 'next/navigation'
3
+ import { Metadata } from 'next'
4
+ import { getToolBySlug , getAllTools } from '@/actions/tool-actions'
5
+ import ComparisonPageLayout from '@/components/ComparisonPageLayout'
6
+
7
+ import { createMetadata } from '@/utils/createMetadata'
8
+ import { ComparisonPageSkeleton } from '@/components/comparison-page-skeleton'
9
+
10
+ interface PageProps {
11
+ params : Promise < {
12
+ tool1 : string
13
+ tool2 : string
14
+ } >
15
+ }
16
+
17
+ // Generate static params for all possible tool combinations
18
+ export async function generateStaticParams ( ) {
19
+ try {
20
+ const tools = await getAllTools ( )
21
+ const params = [ ]
22
+
23
+ // Generate all possible combinations of tools
24
+ for ( let i = 0 ; i < tools . length ; i ++ ) {
25
+ for ( let j = i + 1 ; j < tools . length ; j ++ ) {
26
+ const tool1 = tools [ i ]
27
+ const tool2 = tools [ j ]
28
+
29
+ // Create slug from tool name
30
+ const createSlug = ( name : string ) => {
31
+ return name
32
+ . toLowerCase ( )
33
+ . replace ( / [ ^ a - z 0 - 9 \s - ] / g, '' ) // Remove special characters except spaces and hyphens
34
+ . replace ( / \s + / g, '-' ) // Replace spaces with hyphens
35
+ . replace ( / - + / g, '-' ) // Replace multiple hyphens with single hyphen
36
+ . replace ( / ^ - | - $ / g, '' ) // Remove leading/trailing hyphens
37
+ }
38
+
39
+ const tool1Slug = createSlug ( tool1 . name )
40
+ const tool2Slug = createSlug ( tool2 . name )
41
+
42
+ // Add both combinations (tool1 vs tool2 and tool2 vs tool1)
43
+ params . push ( {
44
+ tool1 : tool1Slug ,
45
+ tool2 : tool2Slug
46
+ } )
47
+ params . push ( {
48
+ tool1 : tool2Slug ,
49
+ tool2 : tool1Slug
50
+ } )
51
+ }
52
+ }
53
+
54
+ console . log ( `Generated ${ params . length } static params for comparison routes` )
55
+ return params
56
+ } catch ( error ) {
57
+ console . error ( 'Error generating static params for comparisons:' , error )
58
+ return [ ]
59
+ }
60
+ }
61
+
62
+ // Generate metadata for SEO
63
+ export async function generateMetadata ( { params } : PageProps ) : Promise < Metadata > {
64
+ const { tool1 : tool1Slug , tool2 : tool2Slug } = await params
65
+
66
+ try {
67
+ const [ tool1 , tool2 ] = await Promise . all ( [
68
+ getToolBySlug ( tool1Slug ) ,
69
+ getToolBySlug ( tool2Slug )
70
+ ] )
71
+
72
+ if ( ! tool1 || ! tool2 ) {
73
+ return createMetadata ( {
74
+ title : "Comparison Not Found" ,
75
+ description : "The requested tool comparison could not be found."
76
+ } )
77
+ }
78
+
79
+ return createMetadata ( {
80
+ title : `${ tool1 . name } vs ${ tool2 . name } ` ,
81
+ description : `Compare ${ tool1 . name } and ${ tool2 . name } - features, pricing, pros and cons. Find the best tool for your development needs.` ,
82
+ slug : `${ tool1Slug } -vs-${ tool2Slug } `
83
+ } )
84
+ } catch ( error ) {
85
+ console . error ( 'Error generating metadata:' , error )
86
+ return createMetadata ( {
87
+ title : "Comparison Error" ,
88
+ description : "Error loading comparison data."
89
+ } )
90
+ }
91
+ }
92
+
93
+ async function ComparisonContent ( { tool1Slug, tool2Slug } : { tool1Slug : string , tool2Slug : string } ) {
94
+ try {
95
+ const [ tool1 , tool2 ] = await Promise . all ( [
96
+ getToolBySlug ( tool1Slug ) ,
97
+ getToolBySlug ( tool2Slug )
98
+ ] )
99
+
100
+ if ( ! tool1 || ! tool2 ) {
101
+ notFound ( )
102
+ }
103
+
104
+ // Generate simple comparison prose
105
+ const proseParagraphs = [
106
+ `Choosing between ${ tool1 . name } and ${ tool2 . name } is a common decision for developers. Both tools have their unique strengths and serve different use cases in the development workflow.` ,
107
+ `${ tool1 . name } ${ tool1 . description ? `is ${ tool1 . description . toLowerCase ( ) } ` : 'offers a comprehensive set of features' } , making it suitable for teams that prioritize reliability and ease of use.` ,
108
+ `${ tool2 . name } ${ tool2 . description ? `focuses on ${ tool2 . description . toLowerCase ( ) } ` : 'provides powerful capabilities' } , which appeals to developers who value performance and flexibility.` ,
109
+ `When making your decision, consider factors like your budget, team size, integration requirements, and long-term scalability needs. This comparison will help you understand which tool aligns better with your specific requirements.`
110
+ ]
111
+
112
+ return (
113
+ < ComparisonPageLayout
114
+ tool1 = { tool1 }
115
+ tool2 = { tool2 }
116
+ proseParagraphs = { proseParagraphs }
117
+ />
118
+ )
119
+ } catch ( error ) {
120
+ console . error ( 'Error loading comparison:' , error )
121
+ throw error
122
+ }
123
+ }
124
+
125
+ export default async function ComparisonPage ( { params } : PageProps ) {
126
+ const { tool1 : tool1Slug , tool2 : tool2Slug } = await params
127
+
128
+ return (
129
+ < Suspense fallback = { < ComparisonPageSkeleton /> } >
130
+ < ComparisonContent tool1Slug = { tool1Slug } tool2Slug = { tool2Slug } />
131
+ </ Suspense >
132
+ )
133
+ }
134
+
135
+ // Enable ISR with 1 hour revalidation
136
+ export const revalidate = 3600
0 commit comments