public: add more content

This commit is contained in:
Carl-Gerhard Lindesvärd
2026-02-25 22:27:04 +01:00
parent f311146ade
commit 38d9b65ec8
42 changed files with 1864 additions and 315 deletions

View File

@@ -165,6 +165,7 @@ export interface RelatedLink {
}
export interface RelatedLinks {
guides?: RelatedLink[];
articles?: RelatedLink[];
alternatives?: RelatedLink[];
}

114
apps/public/src/lib/for.ts Normal file
View File

@@ -0,0 +1,114 @@
import { readdirSync, readFileSync } from 'node:fs';
import { join } from 'node:path';
export interface ForSeo {
title: string;
description: string;
noindex?: boolean;
}
export interface ForHero {
heading: string;
subheading: string;
badges: string[];
}
export interface ForProblem {
title: string;
intro: string;
items: Array<{
title: string;
description: string;
}>;
}
export interface ForFeature {
title: string;
description: string;
icon?: string;
}
export interface ForFeatures {
title: string;
intro: string;
items: ForFeature[];
}
export interface ForBenefit {
title: string;
description: string;
}
export interface ForBenefits {
title: string;
intro: string;
items: ForBenefit[];
}
export interface ForFaq {
question: string;
answer: string;
}
export interface ForFaqs {
title: string;
intro: string;
items: ForFaq[];
}
export interface ForCta {
label: string;
href: string;
}
export interface ForRelatedLinks {
articles?: Array<{ title: string; url: string }>;
guides?: Array<{ title: string; url: string }>;
comparisons?: Array<{ title: string; url: string }>;
}
export interface ForData {
url: string;
slug: string;
audience: string;
seo: ForSeo;
hero: ForHero;
problem: ForProblem;
features: ForFeatures;
benefits: ForBenefits;
faqs: ForFaqs;
related_links?: ForRelatedLinks;
ctas: {
primary: ForCta;
secondary: ForCta;
};
}
const contentDir = join(process.cwd(), 'content', 'for');
export async function getForData(slug: string): Promise<ForData | null> {
try {
const filePath = join(contentDir, `${slug}.json`);
const fileContents = readFileSync(filePath, 'utf8');
const data = JSON.parse(fileContents) as ForData;
return {
...data,
url: `/for/${slug}`,
};
} catch (error) {
console.error(`Error loading for data for ${slug}:`, error);
return null;
}
}
export async function getAllForSlugs(): 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 for directory:', error);
return [];
}
}

View File

@@ -1,8 +1,11 @@
import type { Metadata } from 'next';
import { OPENPANEL_DESCRIPTION, OPENPANEL_NAME } from './openpanel-brand';
import {
OPENPANEL_DESCRIPTION,
OPENPANEL_SITE_NAME,
} from './openpanel-brand';
import { url as baseUrl } from './layout.shared';
const siteName = OPENPANEL_NAME;
const siteName = OPENPANEL_SITE_NAME;
const defaultDescription = OPENPANEL_DESCRIPTION;
const defaultImage = baseUrl('/ogimage.png');

View File

@@ -1,4 +1,5 @@
export const OPENPANEL_NAME = 'OpenPanel';
export const OPENPANEL_SITE_NAME = 'OpenPanel Analytics';
export const OPENPANEL_BASE_URL = 'https://openpanel.dev';
export const OPENPANEL_DESCRIPTION =
'OpenPanel is an open-source web and product analytics platform, an open-source alternative to Mixpanel with optional self-hosting.';