From 621302bac336b9bb9dd3302f929d97f10150e5d5 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Mon, 13 Jul 2026 16:50:46 -0700 Subject: [PATCH] fix(landing): rename /comparison route to /comparisons for naming consistency Aligns with the /integrations/[slug] convention (plural category, singular item). Adds a 301 redirect (both the bare hub page and every competitor detail page) so previously indexed URLs keep working, and updates every internal reference: footer nav, sitemap generation, and all import specifiers/canonical URLs/breadcrumb JSON-LD within the route itself. --- .../[provider]/page.tsx | 20 +++++++++---------- .../comparison-sections.ts | 0 .../brand-icon-tile/brand-icon-tile.tsx | 0 .../components/brand-icon-tile/index.ts | 0 .../comparison-cards/comparison-cards.tsx | 2 +- .../components/comparison-cards/index.ts | 0 .../comparison-table/comparison-table.tsx | 6 +++--- .../components/comparison-table/index.ts | 0 .../components/fact-value/fact-value.tsx | 4 ++-- .../components/fact-value/index.ts | 0 .../components/source-info/index.ts | 0 .../components/source-info/source-info.tsx | 0 .../fact-status.ts | 0 .../{comparison => comparisons}/not-found.tsx | 2 +- .../{comparison => comparisons}/page.tsx | 14 ++++++------- .../{comparison => comparisons}/utils.ts | 0 .../(landing)/components/footer/footer.tsx | 2 +- apps/sim/app/sitemap.ts | 6 +++--- apps/sim/next.config.ts | 19 ++++++++++++++++++ 19 files changed, 47 insertions(+), 28 deletions(-) rename apps/sim/app/(landing)/{comparison => comparisons}/[provider]/page.tsx (94%) rename apps/sim/app/(landing)/{comparison => comparisons}/comparison-sections.ts (100%) rename apps/sim/app/(landing)/{comparison => comparisons}/components/brand-icon-tile/brand-icon-tile.tsx (100%) rename apps/sim/app/(landing)/{comparison => comparisons}/components/brand-icon-tile/index.ts (100%) rename apps/sim/app/(landing)/{comparison => comparisons}/components/comparison-cards/comparison-cards.tsx (95%) rename apps/sim/app/(landing)/{comparison => comparisons}/components/comparison-cards/index.ts (100%) rename apps/sim/app/(landing)/{comparison => comparisons}/components/comparison-table/comparison-table.tsx (98%) rename apps/sim/app/(landing)/{comparison => comparisons}/components/comparison-table/index.ts (100%) rename apps/sim/app/(landing)/{comparison => comparisons}/components/fact-value/fact-value.tsx (94%) rename apps/sim/app/(landing)/{comparison => comparisons}/components/fact-value/index.ts (100%) rename apps/sim/app/(landing)/{comparison => comparisons}/components/source-info/index.ts (100%) rename apps/sim/app/(landing)/{comparison => comparisons}/components/source-info/source-info.tsx (100%) rename apps/sim/app/(landing)/{comparison => comparisons}/fact-status.ts (100%) rename apps/sim/app/(landing)/{comparison => comparisons}/not-found.tsx (91%) rename apps/sim/app/(landing)/{comparison => comparisons}/page.tsx (95%) rename apps/sim/app/(landing)/{comparison => comparisons}/utils.ts (100%) diff --git a/apps/sim/app/(landing)/comparison/[provider]/page.tsx b/apps/sim/app/(landing)/comparisons/[provider]/page.tsx similarity index 94% rename from apps/sim/app/(landing)/comparison/[provider]/page.tsx rename to apps/sim/app/(landing)/comparisons/[provider]/page.tsx index cafff5b7347..2209e94a97c 100644 --- a/apps/sim/app/(landing)/comparison/[provider]/page.tsx +++ b/apps/sim/app/(landing)/comparisons/[provider]/page.tsx @@ -4,10 +4,10 @@ import type { CompetitorProfile } from '@/lib/compare/data' import { simProfile } from '@/lib/compare/data' import { SITE_URL } from '@/lib/core/utils/urls' import { buildLandingMetadata } from '@/lib/landing/seo' -import { COMPARISON_SECTIONS, getFactGroup } from '@/app/(landing)/comparison/comparison-sections' -import { BrandIconTile, SimIconTile } from '@/app/(landing)/comparison/components/brand-icon-tile' -import { ComparisonCards } from '@/app/(landing)/comparison/components/comparison-cards' -import { ComparisonTable } from '@/app/(landing)/comparison/components/comparison-table' +import { COMPARISON_SECTIONS, getFactGroup } from '@/app/(landing)/comparisons/comparison-sections' +import { BrandIconTile, SimIconTile } from '@/app/(landing)/comparisons/components/brand-icon-tile' +import { ComparisonCards } from '@/app/(landing)/comparisons/components/comparison-cards' +import { ComparisonTable } from '@/app/(landing)/comparisons/components/comparison-table' import { ALL_COMPETITORS, buildBottomLine, @@ -15,7 +15,7 @@ import { getCompetitorBySlug, getLatestVerifiedDate, SIM_LATEST_VERIFIED, -} from '@/app/(landing)/comparison/utils' +} from '@/app/(landing)/comparisons/utils' import { BackLink } from '@/app/(landing)/components' import { Cta } from '@/app/(landing)/components/cta/cta' import { JsonLd } from '@/app/(landing)/components/json-ld' @@ -57,7 +57,7 @@ export async function generateMetadata({ return buildLandingMetadata({ title: `Sim vs ${competitor.name} | Sim, the AI Workspace`, description: `Compare Sim, the open-source AI workspace, to ${competitor.name} on platform, AI, integrations, pricing, security, and support. Sourced and dated facts.`, - path: `/comparison/${competitor.id}`, + path: `/comparisons/${competitor.id}`, keywords: [ `Sim vs ${competitor.name}`, `${competitor.name} alternative`, @@ -91,12 +91,12 @@ export default async function ComparisonProviderPage({ '@type': 'BreadcrumbList', itemListElement: [ { '@type': 'ListItem', position: 1, name: 'Home', item: baseUrl }, - { '@type': 'ListItem', position: 2, name: 'Comparison', item: `${baseUrl}/comparison` }, + { '@type': 'ListItem', position: 2, name: 'Comparisons', item: `${baseUrl}/comparisons` }, { '@type': 'ListItem', position: 3, name: `Sim vs ${competitor.name}`, - item: `${baseUrl}/comparison/${competitor.id}`, + item: `${baseUrl}/comparisons/${competitor.id}`, }, ], } @@ -110,7 +110,7 @@ export default async function ComparisonProviderPage({ '@type': 'ItemList', name: `Sim vs ${competitor.name}`, description: `Feature and pricing comparison between Sim and ${competitor.name}.`, - url: `${baseUrl}/comparison/${competitor.id}`, + url: `${baseUrl}/comparisons/${competitor.id}`, dateModified: latestVerified.toISOString().slice(0, 10), numberOfItems: 2, itemListElement: [ @@ -163,7 +163,7 @@ export default async function ComparisonProviderPage({
- +
diff --git a/apps/sim/app/(landing)/comparison/comparison-sections.ts b/apps/sim/app/(landing)/comparisons/comparison-sections.ts similarity index 100% rename from apps/sim/app/(landing)/comparison/comparison-sections.ts rename to apps/sim/app/(landing)/comparisons/comparison-sections.ts diff --git a/apps/sim/app/(landing)/comparison/components/brand-icon-tile/brand-icon-tile.tsx b/apps/sim/app/(landing)/comparisons/components/brand-icon-tile/brand-icon-tile.tsx similarity index 100% rename from apps/sim/app/(landing)/comparison/components/brand-icon-tile/brand-icon-tile.tsx rename to apps/sim/app/(landing)/comparisons/components/brand-icon-tile/brand-icon-tile.tsx diff --git a/apps/sim/app/(landing)/comparison/components/brand-icon-tile/index.ts b/apps/sim/app/(landing)/comparisons/components/brand-icon-tile/index.ts similarity index 100% rename from apps/sim/app/(landing)/comparison/components/brand-icon-tile/index.ts rename to apps/sim/app/(landing)/comparisons/components/brand-icon-tile/index.ts diff --git a/apps/sim/app/(landing)/comparison/components/comparison-cards/comparison-cards.tsx b/apps/sim/app/(landing)/comparisons/components/comparison-cards/comparison-cards.tsx similarity index 95% rename from apps/sim/app/(landing)/comparison/components/comparison-cards/comparison-cards.tsx rename to apps/sim/app/(landing)/comparisons/components/comparison-cards/comparison-cards.tsx index 8a3d62e4745..d50a7973ab7 100644 --- a/apps/sim/app/(landing)/comparison/components/comparison-cards/comparison-cards.tsx +++ b/apps/sim/app/(landing)/comparisons/components/comparison-cards/comparison-cards.tsx @@ -1,5 +1,5 @@ import type { FactSource } from '@/lib/compare/data' -import { SourceLink } from '@/app/(landing)/comparison/components/source-info' +import { SourceLink } from '@/app/(landing)/comparisons/components/source-info' interface ComparisonCardItem { title: string diff --git a/apps/sim/app/(landing)/comparison/components/comparison-cards/index.ts b/apps/sim/app/(landing)/comparisons/components/comparison-cards/index.ts similarity index 100% rename from apps/sim/app/(landing)/comparison/components/comparison-cards/index.ts rename to apps/sim/app/(landing)/comparisons/components/comparison-cards/index.ts diff --git a/apps/sim/app/(landing)/comparison/components/comparison-table/comparison-table.tsx b/apps/sim/app/(landing)/comparisons/components/comparison-table/comparison-table.tsx similarity index 98% rename from apps/sim/app/(landing)/comparison/components/comparison-table/comparison-table.tsx rename to apps/sim/app/(landing)/comparisons/components/comparison-table/comparison-table.tsx index 2b13db94836..a5208b43ab9 100644 --- a/apps/sim/app/(landing)/comparison/components/comparison-table/comparison-table.tsx +++ b/apps/sim/app/(landing)/comparisons/components/comparison-table/comparison-table.tsx @@ -1,9 +1,9 @@ import type { ReactNode } from 'react' import { cn } from '@sim/emcn' import type { CompetitorProfile } from '@/lib/compare/data' -import { COMPARISON_SECTIONS, getFactGroup } from '@/app/(landing)/comparison/comparison-sections' -import { BrandIconTile, SimIconTile } from '@/app/(landing)/comparison/components/brand-icon-tile' -import { FactValue } from '@/app/(landing)/comparison/components/fact-value' +import { COMPARISON_SECTIONS, getFactGroup } from '@/app/(landing)/comparisons/comparison-sections' +import { BrandIconTile, SimIconTile } from '@/app/(landing)/comparisons/components/brand-icon-tile' +import { FactValue } from '@/app/(landing)/comparisons/components/fact-value' export interface ComparisonTableProps { sim: CompetitorProfile diff --git a/apps/sim/app/(landing)/comparison/components/comparison-table/index.ts b/apps/sim/app/(landing)/comparisons/components/comparison-table/index.ts similarity index 100% rename from apps/sim/app/(landing)/comparison/components/comparison-table/index.ts rename to apps/sim/app/(landing)/comparisons/components/comparison-table/index.ts diff --git a/apps/sim/app/(landing)/comparison/components/fact-value/fact-value.tsx b/apps/sim/app/(landing)/comparisons/components/fact-value/fact-value.tsx similarity index 94% rename from apps/sim/app/(landing)/comparison/components/fact-value/fact-value.tsx rename to apps/sim/app/(landing)/comparisons/components/fact-value/fact-value.tsx index 2e95baf01dd..88f1f6f01ef 100644 --- a/apps/sim/app/(landing)/comparison/components/fact-value/fact-value.tsx +++ b/apps/sim/app/(landing)/comparisons/components/fact-value/fact-value.tsx @@ -1,7 +1,7 @@ import { Check, X } from '@sim/emcn/icons' import type { Fact } from '@/lib/compare/data' -import { SourceLink } from '@/app/(landing)/comparison/components/source-info' -import { parseFactValue } from '@/app/(landing)/comparison/fact-status' +import { SourceLink } from '@/app/(landing)/comparisons/components/source-info' +import { parseFactValue } from '@/app/(landing)/comparisons/fact-status' export interface FactValueProps { fact: Fact diff --git a/apps/sim/app/(landing)/comparison/components/fact-value/index.ts b/apps/sim/app/(landing)/comparisons/components/fact-value/index.ts similarity index 100% rename from apps/sim/app/(landing)/comparison/components/fact-value/index.ts rename to apps/sim/app/(landing)/comparisons/components/fact-value/index.ts diff --git a/apps/sim/app/(landing)/comparison/components/source-info/index.ts b/apps/sim/app/(landing)/comparisons/components/source-info/index.ts similarity index 100% rename from apps/sim/app/(landing)/comparison/components/source-info/index.ts rename to apps/sim/app/(landing)/comparisons/components/source-info/index.ts diff --git a/apps/sim/app/(landing)/comparison/components/source-info/source-info.tsx b/apps/sim/app/(landing)/comparisons/components/source-info/source-info.tsx similarity index 100% rename from apps/sim/app/(landing)/comparison/components/source-info/source-info.tsx rename to apps/sim/app/(landing)/comparisons/components/source-info/source-info.tsx diff --git a/apps/sim/app/(landing)/comparison/fact-status.ts b/apps/sim/app/(landing)/comparisons/fact-status.ts similarity index 100% rename from apps/sim/app/(landing)/comparison/fact-status.ts rename to apps/sim/app/(landing)/comparisons/fact-status.ts diff --git a/apps/sim/app/(landing)/comparison/not-found.tsx b/apps/sim/app/(landing)/comparisons/not-found.tsx similarity index 91% rename from apps/sim/app/(landing)/comparison/not-found.tsx rename to apps/sim/app/(landing)/comparisons/not-found.tsx index 8a22c0f44c6..79f529b3b46 100644 --- a/apps/sim/app/(landing)/comparison/not-found.tsx +++ b/apps/sim/app/(landing)/comparisons/not-found.tsx @@ -18,7 +18,7 @@ export default function ComparisonNotFound() {

The comparison you're looking for doesn't exist or has been moved.

- + Browse comparisons
diff --git a/apps/sim/app/(landing)/comparison/page.tsx b/apps/sim/app/(landing)/comparisons/page.tsx similarity index 95% rename from apps/sim/app/(landing)/comparison/page.tsx rename to apps/sim/app/(landing)/comparisons/page.tsx index 973911e78e4..fdf95f5619b 100644 --- a/apps/sim/app/(landing)/comparison/page.tsx +++ b/apps/sim/app/(landing)/comparisons/page.tsx @@ -3,8 +3,8 @@ import Link from 'next/link' import { simProfile } from '@/lib/compare/data' import { SITE_URL } from '@/lib/core/utils/urls' import { buildLandingMetadata } from '@/lib/landing/seo' -import { BrandIconTile } from '@/app/(landing)/comparison/components/brand-icon-tile' -import { ALL_COMPETITORS, ensurePeriod, lowercaseFirst } from '@/app/(landing)/comparison/utils' +import { BrandIconTile } from '@/app/(landing)/comparisons/components/brand-icon-tile' +import { ALL_COMPETITORS, ensurePeriod, lowercaseFirst } from '@/app/(landing)/comparisons/utils' import { ChevronArrow } from '@/app/(landing)/components/chevron-arrow' import { JsonLd } from '@/app/(landing)/components/json-ld' import { LandingFAQ } from '@/app/(landing)/components/landing-faq' @@ -47,7 +47,7 @@ export const metadata: Metadata = buildLandingMetadata({ title: 'Sim Comparisons | Sim, the AI Workspace', description: 'Compare Sim, the open-source AI workspace, to n8n, Zapier, Make, and other workflow automation and AI agent platforms. Sourced, dated, fact-checked.', - path: '/comparison', + path: '/comparisons', keywords: [ 'Sim comparison', 'Sim vs n8n', @@ -65,7 +65,7 @@ export default function ComparisonHubPage() { '@type': 'BreadcrumbList', itemListElement: [ { '@type': 'ListItem', position: 1, name: 'Home', item: baseUrl }, - { '@type': 'ListItem', position: 2, name: 'Comparison', item: `${baseUrl}/comparison` }, + { '@type': 'ListItem', position: 2, name: 'Comparisons', item: `${baseUrl}/comparisons` }, ], } @@ -74,12 +74,12 @@ export default function ComparisonHubPage() { '@type': 'ItemList', name: 'Sim Comparisons', description: 'Directory of Sim comparison pages against AI agent and workflow platforms.', - url: `${baseUrl}/comparison`, + url: `${baseUrl}/comparisons`, numberOfItems: ALL_COMPETITORS.length, itemListElement: ALL_COMPETITORS.map((competitor, index) => ({ '@type': 'ListItem', position: index + 1, - url: `${baseUrl}/comparison/${competitor.id}`, + url: `${baseUrl}/comparisons/${competitor.id}`, name: `Sim vs ${competitor.name}`, })), } @@ -144,7 +144,7 @@ export default function ComparisonHubPage() { return (
diff --git a/apps/sim/app/(landing)/comparison/utils.ts b/apps/sim/app/(landing)/comparisons/utils.ts similarity index 100% rename from apps/sim/app/(landing)/comparison/utils.ts rename to apps/sim/app/(landing)/comparisons/utils.ts diff --git a/apps/sim/app/(landing)/components/footer/footer.tsx b/apps/sim/app/(landing)/components/footer/footer.tsx index b0849740fba..30e1899273f 100644 --- a/apps/sim/app/(landing)/components/footer/footer.tsx +++ b/apps/sim/app/(landing)/components/footer/footer.tsx @@ -41,7 +41,7 @@ const PRODUCT_LINKS: FooterItem[] = [ const RESOURCES_LINKS: FooterItem[] = [ { label: 'Blog', href: '/blog' }, { label: 'Docs', href: 'https://docs.sim.ai', external: true }, - { label: 'Compare', href: '/comparison' }, + { label: 'Compare', href: '/comparisons' }, { label: 'Careers', href: '/careers' }, { label: 'Changelog', href: '/changelog' }, { label: 'Contact', href: '/contact' }, diff --git a/apps/sim/app/sitemap.ts b/apps/sim/app/sitemap.ts index 30f3c91042c..4d9ad8d77ea 100644 --- a/apps/sim/app/sitemap.ts +++ b/apps/sim/app/sitemap.ts @@ -9,7 +9,7 @@ import { ALL_COMPETITORS, getLatestVerifiedDate, SIM_LATEST_VERIFIED, -} from '@/app/(landing)/comparison/utils' +} from '@/app/(landing)/comparisons/utils' import { ALL_CATALOG_MODELS, MODEL_PROVIDERS_WITH_CATALOGS } from '@/app/(landing)/models/utils' /** One sitemap entry per author, timestamped by their most recently updated post. */ @@ -172,9 +172,9 @@ export default async function sitemap(): Promise { : SIM_LATEST_VERIFIED const comparisonPages: MetadataRoute.Sitemap = [ - { url: `${baseUrl}/comparison`, lastModified: comparisonLastModified }, + { url: `${baseUrl}/comparisons`, lastModified: comparisonLastModified }, ...ALL_COMPETITORS.map((competitor) => ({ - url: `${baseUrl}/comparison/${competitor.id}`, + url: `${baseUrl}/comparisons/${competitor.id}`, lastModified: competitorLastModified(competitor), })), ] diff --git a/apps/sim/next.config.ts b/apps/sim/next.config.ts index 845241d3cd6..7121abafa5e 100644 --- a/apps/sim/next.config.ts +++ b/apps/sim/next.config.ts @@ -455,6 +455,25 @@ const nextConfig: NextConfig = { }) } + /** + * The comparison route was renamed from `/comparison` to `/comparisons` + * for naming consistency with `/integrations/[slug]` (plural category, + * singular item). Preserve previously indexed URLs for the hub page and + * every competitor detail page. + */ + redirects.push( + { + source: '/comparison', + destination: '/comparisons', + permanent: true, + }, + { + source: '/comparison/:path*', + destination: '/comparisons/:path*', + permanent: true, + } + ) + return redirects }, async rewrites() {