298 lines
7.2 KiB
TypeScript
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}`,
|
|
});
|
|
}
|
|
|