Files
stats/apps/public/src/lib/compare.ts
Carl-Gerhard Lindesvärd 50ef4c0d94 fix: add internal links
2025-12-02 14:06:18 +01:00

226 lines
4.4 KiB
TypeScript

import { readFileSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
export interface CompareSeo {
title: string;
description: string;
noindex?: boolean;
}
export interface CompareCta {
label: string;
href: string;
}
export interface CompareHero {
heading: string;
subheading: string;
badges: string[];
}
export interface CompareCompetitor {
name: string;
logo: string;
url: string;
short_description: string;
founded?: number;
headquarters?: string;
}
export interface CompareSummary {
title: string;
intro: string;
one_liner: string;
best_for_openpanel: string[];
best_for_competitor: string[];
}
export interface CompareHighlight {
label: string;
openpanel: string;
competitor: string;
}
export interface CompareHighlights {
title: string;
intro: string;
items: CompareHighlight[];
}
export interface CompareFeature {
name: string;
openpanel: boolean | string;
competitor: boolean | string;
notes?: string | null;
}
export interface CompareFeatureGroup {
group: string;
features: CompareFeature[];
}
export interface CompareFeatureComparison {
title: string;
intro: string;
groups: CompareFeatureGroup[];
}
export interface ComparePricing {
title: string;
intro: string;
openpanel: {
model: string;
description: string;
};
competitor: {
model: string;
description: string;
free_tier?: string;
pricing_url?: string;
};
}
export interface CompareTrust {
data_processing: string;
data_location: string;
self_hosting: boolean;
}
export interface CompareTrustCompliance {
title: string;
intro: string;
openpanel: CompareTrust;
competitor: CompareTrust;
}
export interface CompareUseCase {
title: string;
description: string;
icon?: string;
}
export interface CompareUseCases {
title: string;
intro: string;
items: CompareUseCase[];
}
export interface CompareFaq {
question: string;
answer: string;
}
export interface CompareFaqs {
title: string;
intro: string;
items: CompareFaq[];
}
export interface CompareBenefitsSection {
label?: string;
title: string;
description: string;
cta?: CompareCta;
benefits: string[];
}
export interface CompareTechnicalItem {
label: string;
openpanel: string | string[];
competitor: string | string[];
notes?: string | null;
}
export interface CompareTechnicalComparison {
title: string;
intro: string;
items: CompareTechnicalItem[];
}
export interface CompareMigrationStep {
title: string;
description: string;
}
export interface CompareMigration {
title: string;
intro: string;
difficulty: string;
estimated_time: string;
steps: CompareMigrationStep[];
sdk_compatibility: {
similar_api: boolean;
notes: string;
};
historical_data: {
can_import: boolean;
notes: string;
};
}
export interface RelatedLink {
title?: string;
name?: string;
url: string;
}
export interface RelatedLinks {
articles?: RelatedLink[];
alternatives?: RelatedLink[];
}
export interface CompareData {
url: string;
slug: string;
page_type: 'alternative' | 'vs';
seo: CompareSeo;
hero: CompareHero;
competitor: CompareCompetitor;
summary_comparison: CompareSummary;
highlights: CompareHighlights;
feature_comparison: CompareFeatureComparison;
technical_comparison?: CompareTechnicalComparison;
pricing: ComparePricing;
migration?: CompareMigration;
trust_and_compliance?: CompareTrustCompliance;
use_cases: CompareUseCases;
faqs: CompareFaqs;
benefits_section?: CompareBenefitsSection;
related_links?: RelatedLinks;
ctas: {
primary: CompareCta;
secondary: CompareCta;
};
}
const contentDir = join(process.cwd(), 'content', 'compare');
export async function getCompareData(
slug: string,
): Promise<CompareData | null> {
try {
const filePath = join(contentDir, `${slug}.json`);
const fileContents = readFileSync(filePath, 'utf8');
const data = JSON.parse(fileContents) as CompareData;
return {
...data,
url: `/compare/${slug}`,
};
} catch (error) {
console.error(`Error loading compare data for ${slug}:`, error);
return null;
}
}
export async function getAllCompareSlugs(): Promise<string[]> {
try {
const files = readdirSync(contentDir);
return files
.filter((file) => file.endsWith('.json'))
.map((file) => file.replace('.json', ''));
} catch (error) {
console.error('Error reading compare directory:', error);
return [];
}
}