diff --git a/apps/sim/app/(landing)/comparisons/[provider]/page.tsx b/apps/sim/app/(landing)/comparisons/[provider]/page.tsx
index 000827730f5..f0c18db4341 100644
--- a/apps/sim/app/(landing)/comparisons/[provider]/page.tsx
+++ b/apps/sim/app/(landing)/comparisons/[provider]/page.tsx
@@ -18,11 +18,12 @@ import { QuestionSections } from '@/app/(landing)/comparisons/components/questio
import { getLibraryPostsForCompetitor } from '@/app/(landing)/comparisons/library-links'
import {
ALL_COMPETITORS,
- betterThanQuestion,
+ answersQuestionsInPlace,
buildBottomLine,
buildComparisonFaqs,
getCompetitorBySlug,
getLatestVerifiedDate,
+ getQuestionSectionGroups,
SIM_LATEST_VERIFIED,
} from '@/app/(landing)/comparisons/utils'
import { BackLink, ContentRelatedPosts } from '@/app/(landing)/components'
@@ -96,6 +97,13 @@ export default async function ComparisonProviderPage({
}
const faqs = buildComparisonFaqs(competitor)
+ const questionGroups = getQuestionSectionGroups(competitor)
+ const { lead } = questionGroups
+ const leadAnswer = competitor.leadAnswer ? (
+
+
+
+ ) : null
const relatedPosts = await getLibraryPostsForCompetitor(competitor)
const verdict = buildBottomLine(competitor)
const CompetitorIcon = competitor.brand?.icon
@@ -200,7 +208,7 @@ export default async function ComparisonProviderPage({
>
Sim vs {competitor.name}
- {competitor.leadQuestion && competitor.leadAnswer ? (
+ {lead ? (
- {competitor.leadQuestion}
+ {lead.question}
-
-
-
-
- Every fact below is sourced and dated, last verified {verifiedDate}.
-
+ {leadAnswer}
) : (
- <>
- {competitor.leadAnswer ? (
-
-
-
- ) : null}
-
- Sim is the open-source AI workspace where teams build, deploy, and manage AI
- agents visually, conversationally, or with code. Here is how Sim compares to{' '}
- {competitor.name} on platform architecture, AI capabilities, integrations,
- pricing, security, and support. Every fact below is sourced and dated, last
- verified {verifiedDate}.
-
- >
+ leadAnswer
)}
+
+ {lead
+ ? null
+ : `Sim is the open-source AI workspace where teams build, deploy, and manage AI agents visually, conversationally, or with code. Here is how Sim compares to ${competitor.name} on platform architecture, AI capabilities, integrations, pricing, security, and support. `}
+ Every fact below is sourced and dated, last verified {verifiedDate}.
+
Sim is an open-source AI workspace for building, deploying, and managing AI agents.
This page compares Sim to {competitor.name} across platform architecture, AI
@@ -254,25 +250,7 @@ export default async function ComparisonProviderPage({
>
) : null}
- {competitor.betterThanAnswer ? (
- <>
-
-
- {betterThanQuestion(competitor)}
-
-
-
-
-
-
- >
- ) : null}
- {competitor.questions?.intro ? (
-
- ) : null}
+
>
) : null}
- {competitor.questions?.glance ? (
-
- ) : null}
+
- {competitor.questions?.closing ? (
-
- ) : null}
+
- {competitor.questions ? null : (
+ {answersQuestionsInPlace(competitor) ? null : (
({
- question,
- answer: proseToText(answer),
- }))
+ if (answersQuestionsInPlace(competitor)) {
+ const { lead, opening, glance, closing } = getQuestionSectionGroups(competitor)
+ return [...(lead ? [lead] : []), ...opening, ...glance, ...closing].map(
+ ({ question, answer }) => ({ question, answer: proseToText(answer) })
+ )
}
const name = competitor.name
const facts = competitor.facts
@@ -178,27 +178,32 @@ export function buildComparisonFaqs(competitor: CompetitorProfile): ComparisonFa
return faqs
}
-/** Heading of the section answering {@link CompetitorProfile.betterThanAnswer}. */
-export function betterThanQuestion(competitor: CompetitorProfile): string {
- return `Is Sim better than ${competitor.name}?`
+/**
+ * Whether the page answers its buyer questions as sections (see
+ * {@link CompetitorProfile.questions}). Such a page omits the FAQ block, and its FAQ structured
+ * data lists those questions instead.
+ */
+export function answersQuestionsInPlace(competitor: CompetitorProfile): boolean {
+ return competitor.questions !== undefined
}
/**
- * The buyer questions the page answers in their own sections, grouped by position: `opening`
- * (the lead, "better than", and intro questions) ahead of the product definitions, `glance`
+ * The buyer questions the page answers in their own sections, by position: `lead` in the hero,
+ * `opening` (the "better than" and intro questions) ahead of the product definitions, `glance`
* after the at-a-glance table, and `closing` after the documented limitations.
*/
export function getQuestionSectionGroups(competitor: CompetitorProfile): {
+ lead: ComparisonQuestion | undefined
opening: ComparisonQuestion[]
glance: ComparisonQuestion[]
closing: ComparisonQuestion[]
} {
const { leadQuestion, leadAnswer, betterThanAnswer, questions } = competitor
return {
+ lead: leadQuestion && leadAnswer ? { question: leadQuestion, answer: leadAnswer } : undefined,
opening: [
- ...(leadQuestion && leadAnswer ? [{ question: leadQuestion, answer: leadAnswer }] : []),
...(betterThanAnswer
- ? [{ question: betterThanQuestion(competitor), answer: betterThanAnswer }]
+ ? [{ question: `Is Sim better than ${competitor.name}?`, answer: betterThanAnswer }]
: []),
...(questions?.intro ?? []),
],
@@ -207,12 +212,6 @@ export function getQuestionSectionGroups(competitor: CompetitorProfile): {
}
}
-/** Every question from {@link getQuestionSectionGroups}, in page order. */
-function getQuestionSections(competitor: CompetitorProfile): ComparisonQuestion[] {
- const { opening, glance, closing } = getQuestionSectionGroups(competitor)
- return [...opening, ...glance, ...closing]
-}
-
function proseToText(prose: Prose): string {
return prose.map((segment) => (typeof segment === 'string' ? segment : segment.text)).join('')
}
diff --git a/apps/sim/app/llms-full.txt/route.ts b/apps/sim/app/llms-full.txt/route.ts
index f955ffdf4c7..f1ed68e438a 100644
--- a/apps/sim/app/llms-full.txt/route.ts
+++ b/apps/sim/app/llms-full.txt/route.ts
@@ -80,11 +80,11 @@ function isoDate(date: Date): string {
return date.toISOString().slice(0, 10)
}
-/** The key facts of one `/comparisons/{id}` page as markdown, from the same profile data. */
function questionMarkdown({ question, answer }: ComparisonQuestion): string {
return `**${question}**\n\n${proseToMarkdown(answer)}`
}
+/** The key facts of one `/comparisons/{id}` page as markdown, from the same profile data. */
function comparisonMarkdown(competitor: CompetitorProfile): string {
const verdict = buildBottomLine(competitor)
const questions = getQuestionSectionGroups(competitor)
@@ -104,7 +104,11 @@ function comparisonMarkdown(competitor: CompetitorProfile): string {
`### Sim vs ${competitor.name}`,
`URL: ${toSiteUrl(`/comparisons/${competitor.id}`)} ยท Facts last verified ${isoDate(verified)}`,
`${competitor.name}: ${competitor.oneLiner}`,
- competitor.leadAnswer && !competitor.leadQuestion ? proseToMarkdown(competitor.leadAnswer) : '',
+ questions.lead
+ ? questionMarkdown(questions.lead)
+ : competitor.leadAnswer
+ ? proseToMarkdown(competitor.leadAnswer)
+ : '',
...questions.opening.map(questionMarkdown),
competitor.glance
? [
diff --git a/apps/sim/lib/compare/data/types.ts b/apps/sim/lib/compare/data/types.ts
index fa9af61bb9e..68e82d57727 100644
--- a/apps/sim/lib/compare/data/types.ts
+++ b/apps/sim/lib/compare/data/types.ts
@@ -258,8 +258,8 @@ export interface CompetitorProfile {
*/
leadAnswer?: Prose
/**
- * The question {@link leadAnswer} answers. When set, the lead renders under it as the page's
- * first section, in place of the generic introduction.
+ * The question {@link leadAnswer} answers. When set, the hero shows the lead answer under it as
+ * a question heading, in place of the generic introduction.
*/
leadQuestion?: string
/**