Skip to content

Commit 1dbe023

Browse files
authored
Merge pull request #782 from zackproser/improve-comparisons-again
Add generateStaticParams to comparison routes to fix 404 errors
2 parents 2339aa7 + dc1af4d commit 1dbe023

File tree

1 file changed

+136
-0
lines changed
  • src/app/comparisons/[tool1]/vs/[tool2]

1 file changed

+136
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
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-z0-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

Comments
 (0)