Files
GNX-WEB/gnx-react/lib/seo/metadata.ts
Iliyan Angelov 76c857b4f5 update
2025-10-10 21:54:39 +03:00

298 lines
7.2 KiB
TypeScript

import { Metadata } from 'next';
// Site Configuration
export const SITE_CONFIG = {
name: 'GNX Soft',
shortName: 'GNX',
description: 'Leading enterprise software development company providing custom solutions, data replication, incident management, AI-powered business intelligence, and comprehensive system integrations for modern businesses.',
url: process.env.NEXT_PUBLIC_SITE_URL || 'https://gnxsoft.com',
ogImage: '/images/og-image.png',
email: 'info@gnxsoft.com',
phone: '+359 896 13 80 30',
address: {
street: 'Tsar Simeon I, 56',
city: 'Burgas',
state: 'BG',
zip: '8000',
country: 'Bulgaria',
},
social: {
linkedin: 'https://www.linkedin.com/company/gnxtech',
github: 'https://github.com/gnxtech',
},
businessHours: 'Monday - Friday: 9:00 AM - 6:00 PM PST',
foundedYear: 2020,
};
// Default SEO Configuration
export const DEFAULT_SEO = {
title: `${SITE_CONFIG.name} | Enterprise Software Development & IT Solutions`,
description: SITE_CONFIG.description,
keywords: [
'Enterprise Software Development',
'Custom Software Development',
'Data Replication Services',
'Incident Management SaaS',
'AI Business Intelligence',
'Backend Engineering',
'Frontend Engineering',
'Systems Integration',
'External Systems Integration',
'Payment Terminal Integration',
'ERP Integration',
'Cloud Platform Integration',
'Fiscal Printer Integration',
'Enterprise Technology Solutions',
'Digital Transformation',
'Software Consulting',
'API Development',
'Microservices Architecture',
'Cloud Migration',
'DevOps Services',
],
};
// Generate metadata for pages
interface PageMetadataProps {
title?: string;
description?: string;
keywords?: string[];
image?: string;
url?: string;
type?: 'website' | 'article' | 'product' | 'service';
publishedTime?: string;
modifiedTime?: string;
author?: string;
noindex?: boolean;
nofollow?: boolean;
}
export function generateMetadata({
title,
description,
keywords = [],
image,
url,
type = 'website',
publishedTime,
modifiedTime,
author,
noindex = false,
nofollow = false,
}: PageMetadataProps = {}): Metadata {
const pageTitle = title
? `${title} | ${SITE_CONFIG.name}`
: DEFAULT_SEO.title;
const pageDescription = description || DEFAULT_SEO.description;
const pageImage = image
? `${SITE_CONFIG.url}${image}`
: `${SITE_CONFIG.url}${SITE_CONFIG.ogImage}`;
const pageUrl = url ? `${SITE_CONFIG.url}${url}` : SITE_CONFIG.url;
const allKeywords = [...DEFAULT_SEO.keywords, ...keywords];
const metadata: Metadata = {
title: pageTitle,
description: pageDescription,
keywords: allKeywords,
authors: [
{
name: author || SITE_CONFIG.name,
url: SITE_CONFIG.url,
},
],
creator: SITE_CONFIG.name,
publisher: SITE_CONFIG.name,
icons: {
icon: '/images/logo-light.png',
shortcut: '/images/logo-light.png',
apple: '/images/logo-light.png',
},
formatDetection: {
email: false,
address: false,
telephone: false,
},
metadataBase: new URL(SITE_CONFIG.url),
alternates: {
canonical: pageUrl,
},
openGraph: {
type: type === 'article' ? 'article' : 'website',
locale: 'en_US',
url: pageUrl,
siteName: SITE_CONFIG.name,
title: pageTitle,
description: pageDescription,
images: [
{
url: pageImage,
width: 1200,
height: 630,
alt: title || SITE_CONFIG.name,
},
],
},
twitter: {
card: 'summary_large_image',
title: pageTitle,
description: pageDescription,
images: [pageImage],
},
robots: {
index: !noindex,
follow: !nofollow,
googleBot: {
index: !noindex,
follow: !nofollow,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
verification: {
google: process.env.NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION,
yandex: process.env.NEXT_PUBLIC_YANDEX_VERIFICATION,
},
};
// Add article-specific metadata
if (type === 'article' && (publishedTime || modifiedTime)) {
metadata.openGraph = {
...metadata.openGraph,
type: 'article',
publishedTime,
modifiedTime,
authors: [author || SITE_CONFIG.name],
};
}
return metadata;
}
// Service-specific metadata generator
export function generateServiceMetadata(service: {
title: string;
description: string;
short_description?: string;
slug: string;
category?: { name: string };
technologies?: string;
duration?: string;
}) {
const keywords = [
service.title,
`${service.title} Services`,
service.category?.name || 'Enterprise Services',
'Custom Development',
'Enterprise Solutions',
];
if (service.technologies) {
const techs = service.technologies.split(',').map((t) => t.trim());
keywords.push(...techs);
}
return generateMetadata({
title: service.title,
description: service.short_description || service.description,
keywords,
url: `/services/${service.slug}`,
type: 'service' as any,
});
}
// Blog-specific metadata generator
export function generateBlogMetadata(post: {
title: string;
description?: string;
excerpt?: string;
slug: string;
image?: string;
published_at?: string;
updated_at?: string;
author?: { name: string };
category?: { name: string };
tags?: string[];
}) {
const keywords = [
post.category?.name || 'Technology',
'Blog',
'Tech Insights',
...(post.tags || []),
];
return generateMetadata({
title: post.title,
description: post.description || post.excerpt,
keywords,
image: post.image,
url: `/insights/${post.slug}`,
type: 'article',
publishedTime: post.published_at,
modifiedTime: post.updated_at,
author: post.author?.name,
});
}
// Case Study metadata generator
export function generateCaseStudyMetadata(caseStudy: {
title: string;
description?: string;
excerpt?: string;
slug: string;
image?: string;
client_name?: string;
industry?: string;
technologies?: string;
}) {
const keywords = [
'Case Study',
caseStudy.client_name || '',
caseStudy.industry || '',
'Success Story',
'Client Project',
];
if (caseStudy.technologies) {
const techs = caseStudy.technologies.split(',').map((t) => t.trim());
keywords.push(...techs);
}
return generateMetadata({
title: caseStudy.title,
description: caseStudy.description || caseStudy.excerpt,
keywords: keywords.filter(Boolean),
image: caseStudy.image,
url: `/case-study/${caseStudy.slug}`,
type: 'article',
});
}
// Career metadata generator
export function generateCareerMetadata(job: {
title: string;
description?: string;
slug: string;
location?: string;
department?: string;
employment_type?: string;
}) {
const keywords = [
job.title,
'Career',
'Job Opening',
job.department || '',
job.location || '',
job.employment_type || '',
'Join Our Team',
].filter(Boolean);
return generateMetadata({
title: `${job.title} - Careers`,
description: job.description,
keywords,
url: `/career/${job.slug}`,
});
}